|
最新在做LoRa的项目,使用的是STM32L072和SX1276,需要做一个串口透传模块,刚开始做demo的时候不考虑功耗,所以串口发送和接收直接使用下列函数执行 - HAL_UART_Transmit(&Sensor_UartHandle,(unsigned char *)&readcommand, sizeof(vcom_read_command_t), VCOM_START_DELAY);
/ T) W5 c3 N u+ B% ` - HAL_UART_Receive(&Sensor_UartHandle,(unsigned char *)read_temp,UART_BUFFER_MAX_LEN, VCOM_RECV_TIMEOUT);
复制代码 都涉及到了超时时间,而超时时间依赖的是systick中断,接收发送100字节没问题。 但现在需要做低功耗,那么就不允许systick频繁中断了,于是考虑到串口中断接受,但stm32的库提供的函数让人看不明白: - HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)- @& V8 s- Z7 z+ p4 v
- HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
复制代码 尝试一个晚上,现在收发没问题了,网上写的步骤不够详细,先将我的做法例举如下: 1.在串口初始化的时候打开串口中断,M0的芯片只有串口中断,不区分发送或者接收中断: - void CommandUartInit(void)
- f4 U& R! [' d3 q' h, n - {! R' ^% C- J% U# U
- Sensor_UartHandle.Instance = SENSOR_USARTX; ! J8 ^7 h6 U$ p. c
- Sensor_UartHandle.Init.BaudRate = 4800;
% r I& Y( x9 w4 x* C - Sensor_UartHandle.Init.WordLength = UART_WORDLENGTH_9B; /*8-bit data and 1-bit even bit*/
& `* n% c( r0 g" c0 u5 V - Sensor_UartHandle.Init.StopBits = UART_STOPBITS_1;
- t/ ^ F! K' U8 h2 Z( N. J6 Z - Sensor_UartHandle.Init.Parity = UART_PARITY_EVEN;9 s a( A5 N W3 F. r
- Sensor_UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;* s+ N( t* U2 g- M
- Sensor_UartHandle.Init.Mode = UART_MODE_TX_RX;. s% U5 y1 y9 R; G& y4 ?8 q
- if(HAL_UART_Init(&Sensor_UartHandle) != HAL_OK)
* L- j) F! Q9 a- t: X% N - {6 T9 l2 b4 d+ A# q4 u6 k
- /* Initialization Error */
( ~+ \ B& M) e1 o8 e9 D - Error_Handler();
( K. I" {# r z9 G6 U7 G - }( M2 H# j0 H k0 R
- 1 p) k4 S) b* S9 P* R# N
- NVIC_EnableIRQ(USART2_IRQn);3 q8 O# A0 ]) [, B7 R& x' U
- NVIC_ClearPendingIRQ(USART2_IRQn);
6 I, w$ z7 F" H - }
复制代码
3 x4 C1 A& `0 Q4 x8 n: o 2.添加中断处理函数,按照stm32文件惯例,中断函数在stm32xxx_it.c里面添加: - void USART2_IRQHandler(void)+ b% O- |2 S& R3 K$ y
- {
E) q- B' k3 u1 _5 t' b9 U - HAL_UART_IRQHandler(&Sensor_UartHandle);
' `/ z) o# m9 q% b# g - }
复制代码这里需要说明的是,串口发送和接受的处理库已经帮我们做好了,全部封装在 void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) 这个函数里,我们需要做的就是在中断处理函数里面调用这个函数而已,参数填写正确的串口号。 3. 在主循环中调用发送接收函数: - HAL_UART_Transmit_IT(&Sensor_UartHandle,(unsigned char *)&readcommand, sizeof(vcom_read_command_t)); 4 y: d! S) q- l4 V7 K: K
- do{
U, b3 p2 m) y" A# z+ p w+ I# W* h - 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
- temp_state=HAL_UART_GetState(&Sensor_UartHandle); - T1 `$ c7 S3 n) ]2 |+ k3 l* H
- if(temp_state==HAL_UART_STATE_BUSY_RX || temp_state==HAL_UART_STATE_BUSY_TX_RX)
% e5 p5 w2 t4 c8 ?* t3 S: @ - {
- U+ z+ s- O: R& w" r% f& ~ - receive_timeout ++;
3 s% d: h2 j, e - }
6 D6 g( e. `0 U$ B2 T - }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 |