1. 程式人生 > >STM32微控制器ESP8266傳送資料到WiFi接收端程式碼實現

STM32微控制器ESP8266傳送資料到WiFi接收端程式碼實現

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) );
}
}