[应用相关] STM32单片机的串口理解

[复制链接]
572|13
 楼主| o88ne 发表于 2023-4-30 20:26 | 显示全部楼层 |阅读模式

STM32单片机的串口还是很好理解的,编程也不算复杂。当然我更愿意希望其中断系统和51单片机一样的简单。

        对于接收终端,就是RXNE了,这只在接收完成后才产生,在执行USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)代码时不会进入ISR。但麻烦的就是发送有关的中断了:TXE或者TC,根据资料和测试的结果,TXE在复位后就是置1的,即在执行USART_ITConfig(USART1, USART_IT_TXE,  ENABLE)后会立即产生中断请求。因此这造成一个麻烦的问题:如果没有真正的发送数据,TXE中断都会发生,而且没有休止,这将占用很大部分的CPU时间,甚至影响其他程序的运行!

        因此建议的是在初始化时不好启用TXE中断,只在要发送数据(尤其是字符串、数组这样的系列数据)时才启用TXE。在发送完成后立即将其关闭,以免引起不必要的麻烦。

        对于发送,需要注意TXE和TC的差别——这里简单描述一下,假设串口数据寄存器是DR、串口移位寄存器是SR以及TXD引脚TXDpin,其关系是DR->SR->TXDpin。当DR中的数据转移到SR中时TXE置1,如果有数据写入DR时就能将TXE置0;如果SR中的数据全部通过TXDpin移出并且没有数据进入DR,则TC置1。并且需要注意TXE只能通过写DR来置0,不能直接将其清零,而TC可以直接将其写1清零。

        对于发送单个字符可以考虑不用中断,直接以查询方式完成。

        对于发送字符串/数组类的数据,唯一要考虑的是只在最后一个字符发送后关闭发送中断,这里可以分为两种情况:对于发送可显示的字符串,其用0x00作为结尾的,因此在ISR中就用0x00作为关闭发送中断(TXE或者TC)的条件;第二种情况就是发送二进制数据,那就是0x00~0xFF中间的任意数据,就不能用0x00来判断结束了,这时必须知道数据的具体长度。

       这里简单分析上面代码的执行过程:TXE中断产生于前一个字符从DR送入SR,执行效果是后一个字符送入DR。对于第一种情况,如果是可显示字符,就执行USART_SendData来写DR(也就清零了TXE),当最后一个可显示的字符从DR送入SR之后,产生的TXE中断发现要送入DR的是字符是0x00——这当然不行——此时就关闭TXE中断,字符串发送过程就算结束了。当然这时不能忽略一个隐含的结果:那就是最后一个可显示字符从DR转入SR后TXE是置1的,但关闭了TXE中断,因此只要下次再开启TXE中断就会立即进入ISR。对于第二种情况,其结果和第一种的相同。


 楼主| o88ne 发表于 2023-4-30 20:27 | 显示全部楼层
对于第一种情况,其程序可以这么写:其中TXS是保存了要发送数据的字符串,TxCounter1是索引值:

  1. extern __IO uint8_t TxCounter1;
  2. extern uint8_t *TXS;
  3. extern __IO uint8_t TxLen;

  4. void USART1_IRQHandler(void)
  5.     {
  6.         if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  7.             {                                               
  8.                 if(TXS[TxCounter1]) //如果是可显示字符
  9.                     { USART_SendData(USART1,TXS[TxCounter1++]);}
  10.                 else   //发送完成后关闭TXE中断,
  11.                     { USART_ITConfig(USART1,USART_IT_TXE,DISABLE);}                                                        
  12.             }                  
  13.     }

  14.         对于第二种情况,和上面的大同小异,其中TXLen表示要发送的二进制数据长度:

  15. void USART1_IRQHandler(void)
  16.     {
  17.         if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) //对USART_DR的写操作,将该位清零。
  18.             {                                             
  19.                 if(TxCounter1<TxLen)
  20.                     { USART_SendData(USART1,TXS[TxCounter1++]);}
  21.                 else   //发送完成后关闭TXE中断
  22.                     { USART_ITConfig(USART1,USART_IT_TXE,DISABLE);}                                                         
  23.             }                    
  24.     }
 楼主| o88ne 发表于 2023-4-30 20:28 | 显示全部楼层
事实上第一种情况是第二种的特殊形式,就是说可以用第二种情况去发送可显示的字符——当然没人有闲心去数一句话里有多少个字母空格和标点符号!

        在使用时,只要将TXS指向要发送的字符串或者数组,设置TxLen为要发送的数据长度,然后执行USART_ITConfig(USART1, USART_IT_TXE,ENABLE)就立即开始发送过程。
 楼主| o88ne 发表于 2023-4-30 20:29 | 显示全部楼层
用户可以检查TxCounter1来确定发送了多少字节。比如以第二种情况为例:

  1. uint32_t *TXS;
  2. uint8_t TxBuffer1[]="0123456789ABCDEF";
  3. uint8_t DST2[]="ASDFGHJKL";
  4. __IO uint8_t TxLen = 0x00;

  5.      TxLen=8;                               //发送8个字符,最终发送的是01234567
  6.     TXS=(uint32_t *)TxBuffer1;   //将TXS指向字符串TxBuffer1
  7.     TxCounter1=0;                     //复位索引值
  8.     USART_ITConfig(USART1, USART_IT_TXE,ENABLE);   //启用TXE中断,即开始发送过程
  9.     while(TxCounter1!=TxLen);   //等待发送完成

  10.     TXS=(uint32_t *)TxBuffer2;   //同上,最终发送的是ASDFGHJK
  11.     TxCounter1=0;
  12.     USART_ITConfig(USART1, USART_IT_TXE,ENABLE);
  13.     while(TxCounter1!=TxLen);

        以上就是我认为的最佳方案,但串口中断方式数据有多长就中断多少次,我认为还是占用不少CPU时间,相比之下DMA方式就好多了,因为DMA发送字符串时最多中断两次(半传输完成,全传输完成),并且将串口变成类似16C550的器件。
帛灿灿 发表于 2024-3-15 08:27 | 显示全部楼层

ESD静电保护器基本上都是通过静电进行吸收和耗散
Bblythe 发表于 2024-3-15 09:30 | 显示全部楼层

这类型灌封胶一般分为A、B双组份在进行1:1的配比后再进行灌封的操作
周半梅 发表于 2024-3-15 11:26 | 显示全部楼层

同时把异常高压箝制在一个安全水平之内
Pulitzer 发表于 2024-3-15 12:29 | 显示全部楼层

从而抑制电路的振荡。
童雨竹 发表于 2024-3-15 14:25 | 显示全部楼层

当电路出现异常过压并达到其击穿电压时
Wordsworth 发表于 2024-3-15 15:28 | 显示全部楼层

例如下图中在SPI信号线上串联电阻就是为了改善匹配情况
公羊子丹 发表于 2024-3-15 17:24 | 显示全部楼层

即原/副边交错通断。
万图 发表于 2024-3-15 18:27 | 显示全部楼层

般只要关注值、精度、额度功率
Uriah 发表于 2024-3-15 19:30 | 显示全部楼层

会占用PCB的空间,成本也会更高。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

426

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部