你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】Stm32L0串口中断接收使用

[复制链接]
STMCU小助手 发布时间:2021-11-16 23:00

最新在做LoRa的项目,使用的是STM32L072和SX1276,需要做一个串口透传模块,刚开始做demo的时候不考虑功耗,所以串口发送和接收直接使用下列函数执行

  1.   HAL_UART_Transmit(&Sensor_UartHandle,(unsigned char *)&readcommand, sizeof(vcom_read_command_t), VCOM_START_DELAY);
    / T) W5 c3 N  u+ B% `
  2.                 HAL_UART_Receive(&Sensor_UartHandle,(unsigned char *)read_temp,UART_BUFFER_MAX_LEN, VCOM_RECV_TIMEOUT);
复制代码

 都涉及到了超时时间,而超时时间依赖的是systick中断,接收发送100字节没问题。

但现在需要做低功耗,那么就不允许systick频繁中断了,于是考虑到串口中断接受,但stm32的库提供的函数让人看不明白:

  1. HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)- @& V8 s- Z7 z+ p4 v
  2. HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
复制代码

 尝试一个晚上,现在收发没问题了,网上写的步骤不够详细,先将我的做法例举如下:

1.在串口初始化的时候打开串口中断,M0的芯片只有串口中断,不区分发送或者接收中断:

  1. void CommandUartInit(void)
    - f4 U& R! [' d3 q' h, n
  2. {! R' ^% C- J% U# U
  3.   Sensor_UartHandle.Instance         = SENSOR_USARTX; ! J8 ^7 h6 U$ p. c
  4.   Sensor_UartHandle.Init.BaudRate    = 4800;
    % r  I& Y( x9 w4 x* C
  5.   Sensor_UartHandle.Init.WordLength  = UART_WORDLENGTH_9B;    /*8-bit data and 1-bit even bit*/
    & `* n% c( r0 g" c0 u5 V
  6.   Sensor_UartHandle.Init.StopBits    = UART_STOPBITS_1;
    - t/ ^  F! K' U8 h2 Z( N. J6 Z
  7.   Sensor_UartHandle.Init.Parity      = UART_PARITY_EVEN;9 s  a( A5 N  W3 F. r
  8.   Sensor_UartHandle.Init.HwFlowCtl   = UART_HWCONTROL_NONE;* s+ N( t* U2 g- M
  9.   Sensor_UartHandle.Init.Mode        = UART_MODE_TX_RX;. s% U5 y1 y9 R; G& y4 ?8 q
  10.   if(HAL_UART_Init(&Sensor_UartHandle) != HAL_OK)
    * L- j) F! Q9 a- t: X% N
  11.   {6 T9 l2 b4 d+ A# q4 u6 k
  12.     /* Initialization Error */
    ( ~+ \  B& M) e1 o8 e9 D
  13.     Error_Handler();
    ( K. I" {# r  z9 G6 U7 G
  14.   }( M2 H# j0 H  k0 R
  15. 1 p) k4 S) b* S9 P* R# N
  16.   NVIC_EnableIRQ(USART2_IRQn);3 q8 O# A0 ]) [, B7 R& x' U
  17.   NVIC_ClearPendingIRQ(USART2_IRQn);
    6 I, w$ z7 F" H
  18. }
复制代码

3 x4 C1 A& `0 Q4 x8 n: o

 2.添加中断处理函数,按照stm32文件惯例,中断函数在stm32xxx_it.c里面添加:

  1. void USART2_IRQHandler(void)+ b% O- |2 S& R3 K$ y
  2. {
      E) q- B' k3 u1 _5 t' b9 U
  3.         HAL_UART_IRQHandler(&Sensor_UartHandle);
    ' `/ z) o# m9 q% b# g
  4. }
复制代码

这里需要说明的是,串口发送和接受的处理库已经帮我们做好了,全部封装在 void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) 这个函数里,我们需要做的就是在中断处理函数里面调用这个函数而已,参数填写正确的串口号。

3. 在主循环中调用发送接收函数:

  1.   HAL_UART_Transmit_IT(&Sensor_UartHandle,(unsigned char *)&readcommand, sizeof(vcom_read_command_t));       4 y: d! S) q- l4 V7 K: K
  2.         do{
      U, b3 p2 m) y" A# z+ p  w+ I# W* h
  3.                         uart_receive_status = HAL_UART_Receive_IT(&Sensor_UartHandle,(unsigned char *)read_temp,UART_BUFFER_MAX_LEN);$ C  J8 h! F9 j' z# b$ U+ p
  4.                         temp_state=HAL_UART_GetState(&Sensor_UartHandle);        - T1 `$ c7 S3 n) ]2 |+ k3 l* H
  5.                         if(temp_state==HAL_UART_STATE_BUSY_RX || temp_state==HAL_UART_STATE_BUSY_TX_RX)
    % e5 p5 w2 t4 c8 ?* t3 S: @
  6.                         {
    - U+ z+ s- O: R& w" r% f& ~
  7.                             receive_timeout ++;
    3 s% d: h2 j, e
  8.                         }                       
    6 D6 g( e. `0 U$ B2 T
  9.         }while(Sensor_UartHandle.RxXferCount != 0 && receive_timeout < 10000);
复制代码
0 l! H- ?7 h( u

 这里有几点需要说明:

     1)发送没什么好说的,直接调用HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)就可以将数据发送出去,可以发送任意size的数据。

     2)接收函数做的比较恶心,HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size),每调用一次只接收一个字节,自己可以去分析static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)。

     3)说一下这几个函数之间的关系:

           调用HAL_UART_Receive_IT()相当于开启接收中断--->如果有数据,会触发中断USART2_IRQHandler() ---> HAL_UART_IRQHandler() ---> UART_Receive_IT()

            可以看到在HAL_UART_Receive_IT中设置的各种参数,在UART_Receive_IT中都会用到,uhdata = (uint16_t) READ_REG(huart->Instance->RDR);这个就是从串口数据寄存器中获取到的数据。

      4)重新说明下,不管是发送数据还是接收数据都会触发中断,进而最终会调用到 UART_Receive_IT()这个函数,在这个函数里面分别对接收和发送做了处理,可以看看源码。

      5)为了实现接受任意长度的数据,我定义了一个255字节的数组用于接受,然后加了一个超时时间,网上很多用系统时钟做超时,但我为了做低功耗,没有开启systick中断,所以就直接加了一个u32的变量去计数,超时时间要根据自己接收的最长数据调整。

      6)很多人说在接收大数据的时候这个库函数有问题,项目太急,暂时就不研究了,等遇到的时候再研究吧。


7 b& l% [; Z9 s3 v
赞 收藏 评论0 发布时间:2021-11-16 23:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版