使用STM32CubeMX配置串口各种功能
- STM32CubeMX软件的安装
- 接收+空闲中断
- STM32CubeMX配置
- 1.新建工程
- 2. 选择芯片
- 3. 选择时钟和下载方式
- 4. 配置串口
- 5.设置工程消息
- 6.生成代码
- 7.修改生成的代码
- 空闲中断+DMA转运
- STM32CubeMX配置
- 4.配置串口
- 5.设置工程消息
- 6.生成代码
- 7.修改生成的代码
STM32CubeMX软件的安装
STM32CubeMX软件的具体安装过程这篇博客里STM32CubeMX-下载及使用。这里就不在叙述了。
接收+空闲中断
将串口配置为接收和空闲中断,来接收不定长的数据。
原理:两帧数据直接会出现时间间隔。而空闲中断就是当数据在连续接收后有一段时间没有接收到数据时产生的中断。可以依次作为每帧数据的区分。
STM32CubeMX配置
1.新建工程
2. 选择芯片
3. 选择时钟和下载方式
1.时钟外部8m晶振
2.下载方式-st-link
4. 配置串口
5.设置工程消息
6.生成代码
7.修改生成的代码
在usart.c的文件中找到void MX_USART1_UART_Init(void);这个函数,在里面添加这两句。
含义是打开接收,空闲中断。
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
接着找到中断函数。在stm32f1xx_it.c这个文件夹里,大概在204行的位置。写接收的代码
void USART1_IRQHandler(void)
{
static uint8_t i=0;
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) == SET )
{
RxBuff[i++] = READ_REG(huart1.Instance->DR);
if(i==149)
{
i=0;
}
}
if( __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET )
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
Rx_Flag[0]=1;
Rx_Flag[1]=i;
i=0;
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
这段代码的意思是,将接收到的数据放到RxBuff[]数组里。当一帧数据全部发送完成时,进入到空闲中断也就是下面那个if判断函数里,在这里首先清除了空闲中断的标志位,接着将Rx_Flag[0]接收完成的标志位给置一,并且将i的值赋给Rx_Flag[1]表示接收了多长的数据。最后把i的值给清理,为下次接收做准备。
在主函数里判断Rx_Flag[0]接收完成标志位,等于1时,将接收到的数据再发送出去,并且清零这个标志位。
if( Rx_Flag[0]==1)
{
Rx_Flag[0]=0;
HAL_UART_Transmit(&huart1,RxBuff,Rx_Flag[1],0xffff);
}
空闲中断+DMA转运
当数据较多,且频繁发送时,如果还采用来一个数据,进一次中断接收一下的这种方法,会造成频繁进中断,影响主函数的正常运行。那么该怎么接收这类数据呢?这时可以采用空闲+DMA的方式。空闲中断和上面的一样都是为了分开每帧数据,同时告诉我们数据接收完成的。
而DMA则可以直接进行外设到储存的数据转运。他就相当于一个大机器人里分出的一队小机器人。大机器人正常干自己的事,而分出来的小机器人则专心进行数据的搬运,把接收到数据搬到指定的位置。
STM32CubeMX配置
STM32CubeMX配置前3个步骤和上面的一样,这里直接从第4步开始。
4.配置串口
5.设置工程消息
6.生成代码
设置工程和生成代码的步骤和上面的一样,这里也不截图了。
7.修改生成的代码
同样在usart.c这个文件中的void MX_USART1_UART_Init(void)函数里添加这两句函数。
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1,Rx_Buff,150);
第一句是开启空闲中断。
第二句是开启MDA接收,将串口接收到的数据转运到Rx_Buff里,一共需要转运150个数据。
接着在中断函数里填写处理函数。
if(__HAL_UART_GET_FLAG(&huart1 , UART_FLAG_IDLE) == SET )
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
uint8_t len=150-__HAL_DMA_GET_COUNTER(huart1.hdmarx);
HAL_UART_Transmit_DMA(&huart1,Rx_Buff,len);
HAL_UART_Receive_DMA(&huart1,Rx_Buff,150);
}
这一段的含义是首先判断是否有空闲中断的产生。有的话,清除控制中断标志位。同时接收了多少个数据。__HAL_DMA_GET_COUNTER(huart1.hdmarx);函数的意思是还剩余多少个空间没有进行转运。用全空间150减去剩余的空间等于已经转运的空间,也就是DMA转运了多少个,串口接收了多少个数据。
接着将接收到的数据再通过DMA进行转运到tx上转发出去。
最后再次设置DMA转运的地址和个数。