上一篇
esp8266怎么配置
esp8266和USB轉TTL連接
esp8266簡單介紹
esp8266連接路由器
esp8266通過路由器連接在同一局域網中的電腦,建立TCP連接
esp8266使用串口發送數據到電腦上的網絡調試助手
esp8266使用串口通過局域網發送到電腦上自己寫的Java程序
esp8266的透傳模式
esp8266使用透傳模式連接到電腦的網絡調試助手
esp8266使用透傳模式連接到電腦上的java程序
這一篇
esp8266與STM32連接,電腦通過STM32配置esp8266實現聯網發送數據 具體流程如下圖
2=
esp8266怎么和STM32連接(引腳連接)?
STM32CubeMx配置的usart2使用的PA2和PA3要與esp8266的TX和RX對應,但是得反過來接,要么根本發不出去,看來esp8266又印反了 3V3和EN得接到同一個3V上才可以,要不收到的老是errorSTM32使用USART和電腦相互傳輸數據?
將STM32產生的數據發送到電腦的串口調試助手 第一種方式: 使用UASRT傳輸只需要重新定義fputc()函數,直接使用Printf函數就可以將字符串打印到電腦(即通過串口輸出到電腦) 第二種方式: 使用HAL庫中封裝好的UASART函數 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)也可以實現串口輸出 電腦要發送字符串給STM32,那么STM32怎么收到數據,而且知道這個數據什么意思呢? 第一種方式(只能接收定長字符串): HAL庫依舊有封裝好的函數HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout),但是使用這個函數有一個問題,這個函數的額第三個參數是收到的字符串的大小,可是我都沒有發送,怎么提前把這個字符串的大小寫入單片機呢? 其實問題是STM32如何接收不定長的字符串? 【STM32內部產生的數據或者從傳感器中獲取的數據,STM32如果要發送該數據可以直接使用sizeof獲得數據長度作為第三個參數,但是當人為的發送給串口時,由于提前燒入的程序如果要使用HAL庫的USART接收函數的話,需要確定一個字符串長度,那么這個程序就只能接收指定長度的字符串了,那要如何實現不定長也能接收呢?】 第二種方式: DMA+接收結束判斷。這接收結束判斷可以是字節的timeout,也可以是USART_IT_IDLE線路空閑的標志等。這種方式對于需要整幀接收,且通信速度較快或需要占用cpu較少的情況 【詳細的處理方式可見串口USART 收發數據處理方式總結--DMA+USART+USART_Idle_Interrupt】那么如何配置呢?
既然是DMA和空閑接收中斷就需要設置DMA和UASRT的中斷(即在中斷處理函數中需要有DMA1 channel5 global interrupt和USART1 global interrupt) 如果要使用printf輸出到串口的話,就需要重定義fputc函數(定義在usart.c中) 如果要用線路空閑來觸發中斷來結束接收的話,需要有判斷線路是否空閑的函數,這個函數最好還需要在結束接收時將收到的數據保存到自己定義的變量中那么如何實現不定長接收呢,不還是得知道接受的字符串的長度嗎?
是需要知道,這里使用一個結構體來保存字符串和字符串的長度以及一個標記(用來表示一次接收完成,如果不放在結構體里面,使用全局變量的話會比較麻煩) 具體的方法是這樣的:在一開始接收的時候,將收到的字符串保存在結構體中的字符串數組中,而函數要求的大小這個參數設置為比較大的數字(可以是一次接收數據長度的最大值,這里是1024),在判斷線路是否空閑的函數中,當線路空閑時(即一次接收完成時),將收到的字符串的長度保存到這個結構體中的字符串長度變量中,這樣,當需要將收到的字符串再次發出時,就可以使用已知的長度進行發送了,由此實現了不定長接收。 【其原理其實是用一個大空間去接收(看來接收空間夠大就行,不需要定長接收),在接收完成時計算收到的數據長度保存起來(和收到的數據要一一對應,這也是使用結構體的好處),當需要再次發送出去時,就知道這個字符串的長度了,就可以定長發送了】 結構體 #define RX_LEN 1024 typedef struct { uint8_t RX_flag:1; //IDLE receive flag uint16_t RX_Size; //receive length uint8_t RX_pData[RX_LEN]; //DMA receive buffer }USART_RECEIVETYPE; extern USART_RECEIVETYPE UsartType; 下面是程序的流程 首先在main函數中使用HAL_UART_Receive_DMA(&huart1, UsartType.RX_pData, RX_LEN); 開始接收,接收的數據放到結構體中,長度為最大值 然后打開中斷,__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);這個函數進行中斷使能, 具體介紹: /** @brief Enable the specified UART interrupt. * @param __HANDLE__: specifies the UART Handle. * UART Handle selects the USARTx or UARTy peripheral * (USART,UART availability and x,y values depending on device). * @param __INTERRUPT__: specifies the UART interrupt source to enable. * This parameter can be one of the following values: * @arg UART_IT_CTS: CTS change interrupt * @arg UART_IT_LBD: LIN Break detection interrupt * @arg UART_IT_TXE: Transmit Data Register empty interrupt * @arg UART_IT_TC: Transmission complete interrupt * @arg UART_IT_RXNE: Receive Data register not empty interrupt * @arg UART_IT_IDLE: Idle line detection interrupt * @arg UART_IT_PE: Parity Error interrupt * @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) * @retval None * */ #define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) 之后是否需要延時防止接收不到或者防止其他錯誤的發生不是很清楚。 在stm32f1xx_it.c的DMA和USART的中斷函數中并沒有需要重寫的回調函數 在usart.c中實現處理空閑的函數添加到USART的中斷函數中,那么當線路產生空閑時,就會觸發一個中斷,這個空閑處理的函數,就會開始工作,先清空空閑標志以允許繼續接收,然后使用HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)停止此次接收,接著獲得此次接收到的字符串的長度(這里比較深入,有寄存器的問題,不大理解),然后又調用了HAL_UART_Receive_DMA,這個應該和取得的長度是同一個結構體,那么之前的HAL_UART_Receive_DMA又是再干什么呢?(或許是為了解決第一次的傳輸問題,學的不夠深入,還需要學的再深入) 最后就可以使用獲得的長度和字符串將收到的字符串發送出去了,這樣就實現了不定長接收。 【問題】在結構體中定義的是一個uint8_t類型的數組,那么可以按字符串輸出嗎? 可以, HAL_UART_Transmit(&huart1, UsartType.RX_pData, UsartType.RX_Size, 0xFFFF); printf(" %s ",UsartType.RX_pData); 上面兩句一樣的效果 具體代碼: 在usart.c中添加 /* USER CODE BEGIN 1 */ /** * @brief Retargets the C library printf function to the USART. */ int fputc(int ch,FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; } /** * @brief This function handles USART1 IDLE interrupt. */ void UsartReceive_IDLE(UART_HandleTypeDef *huart) { uint32_t temp; if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); HAL_UART_DMAStop(&huart1); temp = huart1.hdmarx->Instance->CNDTR; UsartType.RX_Size = RX_LEN - temp; UsartType.RX_flag=1; HAL_UART_Receive_DMA(&huart1,UsartType.RX_pData,RX_LEN); } } /* USER CODE END 1 */ 在usart.c中實例化結構體 /* USER CODE BEGIN 0 */ USART_RECEIVETYPE UsartType; /* USER CODE END 0 */ 在usart.h中定義結構體 /* USER CODE BEGIN Private defines */ #define RX_LEN 1024 typedef struct { uint8_t RX_flag:1; //IDLE receive flag uint16_t RX_Size; //receive length uint8_t RX_pData[RX_LEN]; //DMA receive buffer }USART_RECEIVETYPE; extern USART_RECEIVETYPE UsartType; /* USER CODE END Private defines */ 在stm32f1xx_it.c的中斷函數中添加 void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ UsartReceive_IDLE(&huart1); /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } 在main.c中main函數中基本的初始化函數后添加 /* USER CODE BEGIN 2 */ HAL_UART_Receive_DMA(&huart1, UsartType.RX_pData, RX_LEN); __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); HAL_Delay(1000); /* USER CODE END 2 */
評論
查看更多