正点原子串口例程解读

首先是串口初始化,这里初始化的是usart3

void esp8266_init(void)
{
    huart_wifi.Instance=ESP8266;    //uart3
    huart_wifi.Init.BaudRate=115200; // 设置波特率为115200
    huart_wifi.Init.WordLength=UART_WORDLENGTH_8B; // 设置数据位长度为8位
    huart_wifi.Init.StopBits=UART_STOPBITS_1; // 设置停止位为1位
    huart_wifi.Init.Parity=UART_PARITY_NONE; // 设置奇偶校验为无
    huart_wifi.Init.Mode=UART_MODE_TX_RX; // 设置模式为接收和发送
    huart_wifi.Init.HwFlowCtl=UART_HWCONTROL_NONE; // 设置硬件流控制为无
    huart_wifi.Init.OverSampling=UART_OVERSAMPLING_16; // 设置过采样为16
    if(HAL_UART_Init(&huart_wifi)!=HAL_OK)
    {
        Error_Handler();
    }
    /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
    HAL_UART_Receive_IT(&huart_wifi, (uint8_t *)uart_recv_it_buf, WIFI_IRQ_RECV_LEN);


}

其中,HAL_UART_Receive_IT开启标志位UART_IT_RXNE后,我们就可以配置uart3的中断函数

void ESP8266_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart_wifi);
}

    函数中用的是hal库的中断函数代码,函数实现比较复杂,我们可以自己写一个中断函数,配合实现。

      这边是按照官方回调函数,在void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart),中定义何时结束数据传输。

        先讲一下调用结构 

由于   HAL_UART_Receive_IT开启接收中断,会调用我们写好的ESP8266_IRQHandler,进入到

HAL_UART_IRQHandler(&huart_wifi);   第一个if语句判断状态寄存器sr中的RXNE:读取数据寄存器不为空 (Read data register not empty)。和控制寄存器cr中的RXNEIERXNE 中断使能 (RXNE interrupt enable),当rxne不为空切使能rxne中断时候,进入UART_Receive_IT(huart);

点击跳转,找到如下

这个函数的实现官方是弱定义,我们可以重写。

调用结构: 调用  → 被调用

HAL_UART_IRQHandler   → UART_Receive_IT  →  HAL_UART_RxCpltCallback。

下面我们看一下正点原子是怎么实现自定义的串口通讯格式。

/**
 * @brief       Rx传输回调函数
 * @param       huart: UART句柄类型指针
 * @retval      无
 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    
    //g_usart_rx_sta  0-13位表示交收到
    if(huart->Instance == ESP8266)             /* 如果是串口3 */
    {
          if((g_wifi_rx_sta & (1<<15)) == 0)      /* 接收未完成 */
          {
              if(g_wifi_rx_sta & (1<<14) )         /* 接收到了0x0d,换行符是由 2个字节组成:0x0D 和 0x0A */
              {
                  if(uart_recv_it_buf[0] != 0x0a) 
                  {
                      g_wifi_rx_sta = 0;         /* 接收错误,重新开始 */
                  }
                  else 
                  {
                      g_wifi_rx_sta |= (1<<15);   /* 接收完成了 */
                  }
              }
              else                                /* 还没收到0X0D */
              {
                  if(uart_recv_it_buf[0] == 0x0d)
                  {
                      g_wifi_rx_sta |= (1<<14);
                  }
                  else
                  {
                      rx_wifi_msg[g_wifi_rx_sta & 0X3FFF] = uart_recv_it_buf[0] ;
                      g_wifi_rx_sta++;
                      if(g_wifi_rx_sta > (WIFI_RX_LEN - 1))
                      {
                          g_wifi_rx_sta = 0;     /* 接收数据错误,重新开始接收 */
                      }
                  }
              }
              
          }
          HAL_UART_Receive_IT(&huart_wifi, (uint8_t *)uart_recv_it_buf, WIFI_IRQ_RECV_LEN);
        
    }
    
    

    
}

打开正点原子f407开发指南,我们看到

        原子的开发手册对接收中断回调函数代码解读非常完整,清晰,大家可以去看下。

注意的是,用串口助手一定要勾选发送新行(结尾自动发送回车符号),因为代码涉及到对 回车的判断( 0x0d  + 0x0a 表示回车符 )。

g_wifi_rx_sta,表示接受状态标识符,uint16_t类型。

        下面我说一下我理解的代码思路

1.在回调函数中判断是否已经接收完成(bit 15 位为1)  g_wifi_rx_sta    &   (1<<15)    ==0

如果接收完成,调用接收中断函数HAL_UART_Receive_IT(&huart_wifi, (uint8_t *)uart_recv_it_buf, WIFI_IRQ_RECV_LEN);

2,如果已经接收到了 回车的前半部分 :0x0d                  g_wifi_rx_sta    &   (1<<14)    ==1

如果 后面接上的是后半部分 0x0a,那么就判定为接收完成(g_wifi_rx_sta |=(1<<15)),相反如果不是,那么g_wifi_rx_sta

置0,重新开始计数。

3,如果还没有接收到回车的前半部分,那么就先判定是否中断里面接受到的buffer:uart_recv_it_buf[0]已经是0x0d,如果是的话,那么将bit14置1,g_wifi_rx_sta    |=  (1<<14)

4,如果uart_recv_it_buf[0]不是是0x0d,那么就接收字符,原子在这里设置了一个 rx_wifi_msg[ buffer_len ] , buffer_len  是你设置的最大接受缓冲区长度,我这里设置最大128 。

前面我们在初始化esp8266已经开启了   HAL_UART_Receive_IT(&huart_wifi, (uint8_t *)uart_recv_it_buf, WIFI_IRQ_RECV_LEN);  意思是每次中断接收 1个字节的数据。

rx_wifi_msg[ g_wifi_rx_sta  & 0x3fff ]=uart_recv_it_buf[0] ,0x3fff因为是0-13位表示接受数据位数,

每次都接受1位数据,直到设定的最大接收值。

g_wifi_rx_sta ++(每次进入中断一次,而且没有接收到回车判定符号 0x0d,那么就会 自加)。

然后就是判定是否接收长度大于设定长度,如果大于,就将    g_wifi_rx_sta=0;。

main函数部分代码。

if (g_wifi_rx_sta & (1<<15) )         /* 接收到了数据? */
        {
            len = g_wifi_rx_sta & 0x3fff;  /* 得到此次接收到的数据长度 */
            printf("\r\n您发送的消息为:\r\n");

            HAL_UART_Transmit(&huart_wifi,(uint8_t*)rx_wifi_msg,len,1000);    /* 发送接收到的数据 */
            while(__HAL_UART_GET_FLAG(&huart_wifi,UART_FLAG_TC)!=SET);           /* 等待发送结束 */
            printf("\r\n\r\n");             /* 插入换行 */
            g_wifi_rx_sta = 0;
        }
        else
        {
            times++;

            if (times % 5000 == 0)
            {
                printf("\r\n正点原子 STM32开发板 串口实验\r\n");
                printf("正点原子@ALIENTEK\r\n\r\n\r\n");
            }

            if (times % 200 == 0) printf("请输入数据,以回车键结束\r\n");

            if (times % 30  == 0) LED0_TOGGLE(); /* 闪烁LED,提示系统正在运行. */

            delay_ms(10);
        }
          
    }

<think>好的,用户想要查找与正点原子相关的示例代码或教程。首先,我需要回忆一下用户提供的引用内容。引用1提到了正点原子的Linux教程,分为裸机代码、嵌入式Linux移植(包括u-boot、Linux内核、根文件系统)和驱动开发。引用2是关于LCD显示的示例代码,引用3是输入捕获的程序解读,引用4是USMART调试工具的使用。这些引用都涉及到不同的开发模块和示例代码。 用户可能是在学习STM32或者嵌入式Linux,需要具体的示例来参考。我应该根据这些引用内容,整理出正点原子常见的示例代码和教程资源。比如,他们的开发板通常配套有丰富的实验例程,比如GPIO控制、定时器、USART通信、LCD显示、文件系统等。此外,他们的教程可能分为初级、中级和高级,涵盖从基础到应用的不同层面。 接下来需要考虑用户可能的实际需求。他们可能正在寻找如何快速上手正点原子的开发板,或者需要某个特定功能的代码示例,比如输入捕获或USMART调试。我应该提供获取这些资源的途径,比如官方资料、在线平台和社区论坛,并举例说明常见的实验内容,这样用户可以根据自己的开发板型号和需求找到对应的资料。 还要注意用户提到的demo或示例代码可能分布在不同的地方,比如资料光盘、官方网站、GitHub等。需要建议用户检查购买开发板时附带的资料,或者访问正点原子的官网下载。另外,社区和论坛如电子工程世界、优快云可能有用户分享的代码和教程,这也是一个资源来源。 最后,生成的相关问题需要围绕用户可能遇到的下一步问题,比如如何移植u-boot、优化LCD显示、调试输入捕获问题,或者使用USMART工具,这些都能帮助用户进一步深入学习和解决问题。</think>根据正点原子官方资料和技术文档,其示例代码主要分布在以下几个方向: ### 一、STM32基础功能示例 1. **GPIO控制** 包含LED流水灯、按键检测、外部中断等基础外设控制代码,通常以`HAL库`和`标准库`双版本提供[^1][^3]。 2. **定时器应用** 如输入捕获实现红外遥控解码(引用[3]中的捕获状态寄存器设计)、PWM电机控制等: ```c // 输入捕获状态寄存器定义(TIM5CH1_CAPTURE_STA) #define CAPTURE_FLAG_DONE 0x80 // 完成捕获标志位 #define CAPTURE_FLAG_HIGH 0x40 // 高电平捕获标志 ``` 3. **通信协议** 包含USART、I2C、SPI等协议实现,如引用[4]中的USMART串口调试工具: ```c usmart_dev.init(72); // 初始化USMART组件(F1系列主频72MHz) ``` ### 二、嵌入式Linux示例 1. **u-boot移植** 提供NAND Flash启动配置、设备树修改模板[^1]。 2. **驱动开发** 涵盖字符设备驱动、GPIO子系统、中断处理等,配套`insmod`/`rmmod`测试脚本。 3. **根文件系统** 使用Buildroot/Yocto构建的定制化文件系统镜像。 ### 三、典型应用场景代码 1. **LCD显示** 引用[2]中的`LCD_ShowChar`函数实现字符渲染,支持多种字号和抗锯齿效果: ```c void LCD_ShowChar(uint16_t x, uint16_t y, char chr, uint8_t size); ``` 2. **文件系统** FATFS移植案例,支持SD卡文件读写操作。 3. **物联网协议** 包含MQTT、CoAP等协议在STM32+ESP8266硬件组合上的实现。 ### 四、获取途径 1. **官方资料** - 开发板配套资料光盘中的`实验例程`目录 - 正点原子在线文档平台(需注册账号) 2. **开源平台** - GitHub搜索`正点原子开源仓库`(注意区分官方和非官方版本) - Gitee镜像仓库(国内访问更稳定) 3. **社区资源** - 电子工程世界论坛的正点原子专区 - 优快云博客#正点原子教程#标签
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值