提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
ESP8266学习基于野火指南者开发板
前言
野火的板子usart1与ch340连接,通过串口发送的数据可以从PC端接收到,但是与8266连接的usart3没有,方便的话可以自己买一个usb转ttl模块,不然调试的时候两眼一抹黑,不知道哪里出了问题。
编程思路参考野火提供的历程,因为自己使用的事HAL库,所以就重写了一份,通过RXNE+IDLE中断进行不定长数据的接收,与8266模块进行通信。优点是可以知道具体接收的数据长度。缺点是需要频繁进出中断。之前尝试过也DMA+IDLE的方式,但是无法知道接收数据的具体长度,我比较菜鸡,没找到更好一点的办法,所以就放弃了。
编程思路:
每次进入Cplt中断,将DR中数据保存到结构体的数组中,字长加1(要记录字长,方便后续在结尾添加\0),当空闲中断(IDLE)产生时,表示一帧数据接受完成,在回调函数中将finish_flag置1。在主函数中不断查询是否标志位置1,如果u1接到一帧数据,通过u3将数据发送给8266,将字长清零,标志位置0,等待下一次数据到来。从8266中接回的数据同理。
一、串口通讯初始化
1)通过32cube直接生成初始化文件,简单方便,模式Asynchronous,波特率115200其他都默认就可以。usart1与usart3配置相同。
2)然后点击右上角生成既可
二、使用步骤
1.串口中断结构体创建
usart.h
#define MAX_RX_LEN 256
typedef struct USART_FRAM{ // 接收结构体框架
uint8_t Finish_flag; // 接收一帧完成
uint16_t RX_Len; // 接收字长
char *Data; // 数组指针,在usart.c中创建数组,指向他,能减少全区变量的创建
}USART_FRAM, *pUSART_FRAM;
2.Cplt中断回调函数(RXNE)
代码如下(示例):
usart.c
/**
* @brief 串口RxCplt中断回调(RXNE)
* @param huart句柄
* @retval NONE
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(USART3 == huart->Instance){
if( ESP8266_Fram.RX_Len < (MAX_RX_LEN - 1) ){
ESP8266_Fram.Data[ESP8266_Fram.RX_Len ++ ] = Usart3_buf;
ESP_Usart3_Start();
}
}
else if(USART1 == huart->Instance){
if( Usart1_Fram.RX_Len < (MAX_RX_LEN - 1) ){
Usart1_Fram.Data[Usart1_Fram.RX_Len ++ ] = Usart1_buf;
Usart1_Start();
}
}
}
3.IDLE回调函数
代码如下(示例):
usart.c
/**
* @brief 串口IDLE中断回调
* @param huart句柄
* @retval NONE
*/
void UART_IDLECallback(UART_HandleTypeDef *huart)
{
uint32_t tmp;
if(USART3 == huart->Instance){
tmp = huart->Instance->SR;
tmp = huart->Instance->DR;
__HAL_UART_CLEAR_IDLEFLAG(huart); //IDLE清除标志位需要先读取SR,再读取DR,手册写的
ESP8266_Fram.Finish_flag = 1;
}
else if(USART1 == huart->Instance){
tmp = huart->Instance->SR;
tmp = huart->Instance->DR;
__HAL_UART_CLEAR_IDLEFLAG(huart);
Usart1_Fram.Finish_flag = 1;
}
}
4.串口IT使能函数封装
/**
* @brief 串口1中断使能
* @param VOID
* @retval NONE
*/
void Usart1_Start(void){
HAL_UART_Receive_IT(&huart1, &Usart1_buf, 1);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
}
/**
* @brief 串口3中断使能(ESP8266)
* @param VOID
* @retval NONE
*/
void ESP_Usart3_Start(void){
HAL_UART_Receive_IT(&huart3, &Usart3_buf, 1);
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);
}
5.返回结构体指针
/**
* @brief 获得U1 fram
* @param VOID
* @retval Usart1_Fram地址
*/
pUSART_FRAM Usart1_GetFram(void){
pUSART_FRAM tmp = &Usart1_Fram;
return tmp;
}
/**
* @brief 获得ESP_fram
* @param VOID
* @retval ESP8266_Fram地址
*/
pUSART_FRAM ESP_GetFram(void){
pUSART_FRAM tmp = &ESP8266_Fram;
return tmp;
}
6.主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
Usart1_Start(); //初始化u1
ESP_Usart3_Start(); //初始化u3
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
pUSART_FRAM pUsart1_Fram = Usart1_GetFram(); //获取u1框架指针
pUSART_FRAM pESP8266_Fram = ESP_GetFram(); //获取u3框架指针
Usart_SendString(&huart3, (uint8_t*)AT);
while (1)
{
if( pUsart1_Fram->Finish_flag ){
pUsart1_Fram->Finish_flag = 0;
pUsart1_Fram->Data[ pUsart1_Fram->RX_Len ] = '\0';
Usart_SendString(&huart3, (uint8_t*)pUsart1_Fram->Data);
memset(pUsart1_Fram->Data, 0, pUsart1_Fram->RX_Len);
pUsart1_Fram->RX_Len = 0;
}
else if( pESP8266_Fram->Finish_flag ){
pESP8266_Fram->Finish_flag = 0;
pESP8266_Fram->Data[ pESP8266_Fram->RX_Len ] = '\0';
Usart_SendString(&huart1, (uint8_t*)pESP8266_Fram->Data);
memset(pESP8266_Fram->Data, 0, pESP8266_Fram->RX_Len);
pESP8266_Fram->RX_Len = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
总结
如果有哪里写的不对,希望大家能帮忙指出,刚刚入门,轻喷
代码放在下面连接中,需要自取
链接:https://pan.baidu.com/s/1xjIGeWwHICtS3IwpeI5w0A
提取码:kxz5