STM32微控制器ESP8266傳送資料到WiFi接收端程式碼實現
阿新 • • 發佈:2019-02-17
ESP8266支援的一些指令看我另一篇博文:http://blog.csdn.net/qq_17242837/article/details/53931712
首先需要配置STM32的串列埠傳送和接收,在本文中基於原子和網上的一些程式修改,使用DMA傳輸,減少CPU佔用,下面列出所有程式碼。
注:傳送使用的是UDP傳輸,在我自己的設計中是能正確執行的,程式中的標頭檔案自己編譯的時候需要什麼自己新增吧,有"usart.h"和"stm32f10x_usart.h",串列埠1配置了C語言重定向,可以使用printf傳送資料,我用於除錯,串列埠2用於與其他器件通訊。
ESP8266程式
標頭檔案:
#ifndef __ESP8266_H #define __ESP8266_H #include "headers.h" void init_esp8266(void); u8* ESP8266_send(char* cmd); #endif /* __ESP8266_H */
C程式:
#include "esp8266.h" extern u16 USART2_RX_Size; extern u8 USART2_RX_FLAG; extern u8 USART2_RX_BUF[USART_REC_LEN]; char* CWMODE = "AT+CWMODE=2\r\n"; char* CIPMUX = "AT+CIPMUX=1\r\n"; /** AT+ CWSAP=<ssid>,<pwd>,<chl>, <ecn> * ssid:WiFi熱點名稱 * pwd: WiFi熱點連線密碼 * chl: 通道 * ecn: 加密方式,0-OPEN,1-WEP,2-WPA_PSK,3-WPA2_PSK,4-WPA_WPA2_PSK */ char* CWSAP = "AT+CWSAP=\"WIFI\",\"12345678\",1,0\r\n"; char* CIPSERVER = "AT+CIPSERVER=1,8080\r\n"; char* CIPSTART = "AT+CIPSTART=1,\"UDP\",\"192.168.4.2\",8080\r\n"; char CIPSEND[50]= "AT+CIPSEND=1,12\r\n"; char* CIPSTATUS = "AT+CIPSTATUS\r\n"; char* CIPCLOSE = "AT+CIPCLOSE\r\n"; u8 len(char str[]) { u8 i = 0; while(str[i++]); return --i; } /** 判斷src字串中是否包含str字串 * input:擷取部分,需要判斷部分 * return: 不包含返回0,包含返回1 */ char haveString(char* str, char* src) { u16 i; u16 j; u16 length = len(str); for(i = 0; i < len(src); i++) { if(src[i] == str[0]) { for(j = 1; j < length; j++) if(src[++i] != str[j]) break; } if(length == j) break; else j = 0; } if(length == j) return 1; else return 0; } /** brief: 傳送指令,直到串列埠接收到響應返回 * input: AT+CMD,指令內容 * @note 在作業系統支援下,可以等待串列埠接收資料事件返回 */ void write(char* str) { SendMulData(str, len(str)); while(!USART2_RX_FLAG); USART2_RX_FLAG = 0; } /** brief: 初始化ESP8266 * in: 無 * retval:無 */ void init_esp8266(void) { printf("----------start esp init-----------\n"); USART2_RX_FLAG = 0; write(CWMODE); write(CIPMUX); write(CWSAP); write(CIPSERVER); write(CIPSTART); ESP8266_send("ESP start.\r\n"); } /** brief:傳送資料到伺服器或上位機 * in: 需傳送資料 * retval:串列埠接收到的資料 */ u8* ESP8266_send(char* cmd) { u8 wait = 10; sprintf(CIPSEND, "AT+CIPSEND=1,%d\r\n", len(cmd)-2); write(CIPSEND); while(!haveString(">", (char*)USART2_RX_BUF) && wait--) Delay_ms(1); SendMulData(cmd, len(cmd)); return USART2_RX_BUF; }
串列埠程式
標頭檔案:
#ifndef __USART_H
#define __USART_H
#include "headers.h"
#define USART_REC_LEN 256 //定義最大接收位元組數 8
void USART_Config(uint32_t baud,uint32_t uart_num);
void SendMulData(char *data, u16 size);
#endif /* __USART1_H */
C程式:
/*************************************** * 檔名 :usart1.c * 描述 :配置USART1 * 實驗平臺:MINI STM32開發板 基於STM32F103C8T6 * 硬體連線:------------------------ * | PA9 - USART1(Tx) | * | PA10 - USART1(Rx) | * ------------------------ * 庫版本 :ST3.0.0 **********************************************************************************/ #include "usart.h" #include <stdarg.h> #include "misc.h" u8 USART1_RX_FLAG = 0; u8 USART2_RX_FLAG = 0; u16 USART1_RX_Size = 0; u16 USART2_RX_Size = 0; u8 USART1_RX_BUF[USART_REC_LEN]; u8 USART2_RX_BUF[USART_REC_LEN]; //接收緩衝,最大USART_REC_LEN個位元組. int fputc(int ch, FILE *f) { USART_SendData(USART1, (unsigned char) ch); while (!(USART1->SR & USART_FLAG_TXE)); return (ch); } void USART_Config(uint32_t baud,uint32_t uart_num) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* config USART1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); if( uart_num == 1) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* USART1 GPIO config */ /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as mn floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } else { RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* USART1 GPIO config */ /* Configure USART1 Tx (PA.2) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.3) as mn floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } /* USART1 mode config */ USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; if( uart_num == 1 ) { // UART1 interrupt USART_ITConfig(USART1,USART_IT_TC,DISABLE); USART_ITConfig(USART1,USART_IT_RXNE,DISABLE); USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; USART_Init(USART1, &USART_InitStructure); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RX_BUF; } else { // UART2 interrupt USART_ITConfig(USART2,USART_IT_TC,DISABLE); USART_ITConfig(USART2,USART_IT_RXNE,DISABLE); USART_ITConfig(USART2,USART_IT_IDLE,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; USART_Init(USART2, &USART_InitStructure); DMA_DeInit(DMA1_Channel6); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_RX_BUF; } DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = USART_REC_LEN;//100 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 記憶體自增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; if( uart_num == 1 ) { DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); USART_Cmd(USART1, ENABLE); } else { DMA_Init(DMA1_Channel6, &DMA_InitStructure); DMA_Cmd(DMA1_Channel6, ENABLE); USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE); USART_Cmd(USART2, ENABLE); } NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void uart1_Rstart_dma(void) { static uint16_t last_size1 = 0; uint16_t x; DMA1_Channel5->CCR &= (uint16_t)(~DMA_CCR1_EN);//close dma DMA1_Channel5->CMAR = (uint32_t)USART1_RX_BUF; DMA1_Channel5->CNDTR = USART_REC_LEN; for( x = USART1_RX_Size; x < last_size1; x++) { USART1_RX_BUF[x] = 0; } last_size1 = USART1_RX_Size; DMA1_Channel5->CCR |= DMA_CCR1_EN;// enable } // usart1 interrupt handle void USART1_IRQHandler(void) { uint32_t temp = 0; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { // 相當於USART_ClearFlag(USART1,USART_IT_IDLE); (函式無效,需軟體讀取清) temp = USART1->SR; temp = USART1->DR; USART1_RX_FLAG = 1; USART1_RX_Size = USART_REC_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); #ifdef debug SendMulData((char*)USART1_RX_BUF, USART1_RX_Size); #endif // DMA reset uart1_Rstart_dma(); } __nop(); } void uart2_Rstart_dma(void) { static uint16_t last_size2 = 0; uint16_t x; DMA1_Channel6->CCR &= (uint16_t)(~DMA_CCR1_EN);//close dma DMA1_Channel6->CMAR = (uint32_t)USART2_RX_BUF; DMA1_Channel6->CNDTR = USART_REC_LEN; for( x = USART2_RX_Size; x < last_size2; x++) { USART2_RX_BUF[x] = 0; } last_size2 = USART2_RX_Size; DMA1_Channel6->CCR |= DMA_CCR1_EN;// enable } // usart1 interrupt handle void USART2_IRQHandler(void) { uint32_t temp = 0; if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) { #ifdef debug printf("\n%s\n", USART2_RX_BUF); #endif // 相當於USART_ClearFlag(USART1,USART_IT_IDLE); (函式無效,需軟體讀取清) temp = USART2->SR; temp = USART2->DR; USART2_RX_FLAG = 1; USART2_RX_Size = USART_REC_LEN - DMA_GetCurrDataCounter(DMA1_Channel6); // DMA reset uart2_Rstart_dma(); } __nop(); } void SendMulData(char *data, u16 size) //最多傳送USART_SEND_LEN位元組 { int i=0; for(; i < size; i++) { USART_SendData(USART2,data[i]); while( !USART_GetFlagStatus(USART2, USART_FLAG_TXE) ); } }