STM32CubeMX--01—INT
-------- 转载请注明出处
-------- 更多笔记请访问我的博客:merafour.blog.163.com
-------- 2016-11-30.冷月追风
-------- email:
注:不特别声明的情况下不区分 UART跟 USART,统称 UART。
前面我们讲了 UART的轮训方式,现在我们来看看在 HAL中如何使用中断方式来接收数据。
中断方式接收数据首先要勾选UART中断:
| HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); |
| HAL_UART_Receive_IT(&huart1, &pData, 1); |
|
uint8_t pData=0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart1, &pData, 1, 0);
HAL_UART_Receive_IT(&huart1, &pData, 1);
}
|
记住,在中断回调函数中我们需要再次调用 HAL_UART_Receive_IT函数,否则下一次就接收不到信号了。
我个人对于这种使用方式并不喜欢,原因很简单:效率太低了。所以我倾向于打破现有的机制,即直接接手串口中断:"USART1_IRQHandler"函数。比如,我自己写一个函数:
|
void terminal1_data_process(uint8_t data)
{
HAL_UART_Transmit(&huart1, &data, 1, 1);
}
|
然后呢:
|
void USART1_IRQHandler(void)
{
terminal1_data_process(USART1->RDR & 0xFF);
HAL_UART_IRQHandler(&huart1);
}
|
上面的 "terminal"函数虽然接收到了数据,但实际上我们需要做一些处理才方便使用,原因是我们不可能每来一个字节就处理一个字节,而中断当中实际上也不适合做一些过于耗时的处理,应尽量简短。所以我们应该将函数写成:
|
void terminal1_data_process(uint8_t data)
{
macro_queue_write(data,cache1_terminal);
}
|
然后在主循环中读取 cache1_terminal中的数据:
|
while (1)
{
if(0==cache_queue_read_byte(&cache1_terminal, &_byte))
{
HAL_UART_Transmit(&huart1, &_byte, 1, 1);
}
HAL_Delay(1);
}
|
|
#define macro_queue_write(_byte,_queue) do{ \
_queue.w_tmp = _queue.index_w+1; \
if(_queue.w_tmp>=sizeof(_queue.buf)) _queue.w_tmp=0; \
_queue.buf[_queue.w_tmp] = _byte; \
if(_queue.w_tmp != _queue.index_r) _queue.index_w=_queue.w_tmp; \
}while(0);
static __inline int cache_queue_read_byte(cache_queue* _cache, uint8_t* _byte)
{
int ret=-1;
_cache->r_tmp = _cache->index_r+1;
if(_cache->r_tmp>=sizeof(_cache->buf)) _cache->r_tmp=0;
if(_cache->r_tmp != _cache->index_w)
{
*_byte = _cache->buf[_cache->r_tmp];
_cache->index_r = _cache->r_tmp;
ret = 0;
}
return ret;
}
#define CACHE_QUEUE_LEN 256
typedef struct{
uint16_t index_r;
uint16_t index_w;
uint16_t w_tmp;
uint16_t r_tmp;
uint8_t buf[CACHE_QUEUE_LEN];
}cache_queue;
|
这是我们刚刚写入跟读取 cache1_terminal的代码。
不过需要注意的是 HAL的 "HAL_UART_Transmit"函数的形参 Timeout设置 0与非 0经测试并不是随意的,有时候 0会死掉,有时候又是非 0会死掉。
附录:
:
附录:
: