中断全过程分为中断发生→中断处理→中断返回。
- 中断发生:当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。
- 中断处理:当CPU收到请求后,暂停当前的工作,装去处理事件B。
- 中断返回:当CPU将事件B处理完毕后,再回到事件A中去被暂停的地方继续处理事件A。
中断可以解决快速的CPU与慢速的外部设备之间传送数据的矛盾,可以分时为多个外部设备服务,提高计算机利用率;能够及时处理应用系统的随机事件,增强系统的实时性。
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:
外设到内存
内存到外设
内存到内存
外设到外设
普通模式
传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若
开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。
循环模式
可用于处理环形缓冲区和连续数据流(例如ADC扫描模式)。当激活循
环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值
进行加载, 并继续响应DMA请求。
CubeMX新建工程,选好芯片后,将PA1设置为output,PB1设置为GPIO_EXTI1
中断使能
将GPIO mode设置为下降沿
RCC设置如下
在Code Generator下勾选
然后生成代码即可,打开工程
思路:PB1接开关,PA1接LED灯,刚开始LED常亮,当按下开关时,LED灭,将PA1的状态翻转过来。
我们在stm32f1xx_hal_gpio.c中可以查看系统默认的回调函数
weak属性的函数表示:如果该函数没有在其他文件中定义,则使用该函数:如果用户在其他地方定义了该函数,则使用用户定义的函数。
我们在mian函数中重新编写回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin==GPIO_PIN_1) //判断外部中断源 { HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1)//翻转PA1状态 }}
将程序烧录进芯片
新建工程,选择芯片后在Connectivity下找到USART1,Mode选择Asynchronous,然后勾选下面的使能
Parameter Settings中设置通信参数,即波特率115200,8位数据位,无奇偶校验,1位停止位,使能接收和发送,16倍过采样。
其他设置相同
思路:①发送数据:在主函数中0.5s进行一次发送hello windows,使用HAL_UART_Transmit_IT函数将接受到的字符原样发回,发送成功产生回调;②接受数据:接收数据后产生回调HAL_UART_RxCpltCallback,接收成功一次就将数据上发一次,然后重新开始接受数据。
定义结构体
//定义测试串口中断函数收发的结构体类型 typedef struct{ UART_HandleTypeDef *huart1; uint8_t rx_buf[20];//接收缓冲区 uint32_t tx_count;//发送成功次数技术标志位 uint32_t rx_flag;//接收完成标志位 }rxtx_it_usart_t; //声明一个结构体并进行初始化 rxtx_it_usart_t rxtx_it_usart={ .huart1=&huart1, };
串口中断回调函数
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(rxtx_it_usart.huart1==huart) { rxtx_it_usart.tx_count++; } }//发送回调 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(rxtx_it_usart.huart1==huart) { rxtx_it_usart .rx_flag=1; } }//接受回调
在主函数中添加以下代码
if((HAL_GetTick()-start_count)>500)//0.5秒发送一次 { start_count=HAL_GetTick(); HAL_UART_Transmit_IT(rxtx_it_usart.huart1,send_data,sizeof(send_data)-1); } if(rxtx_it_usart.rx_flag==1)//接收成功一次就将数据上发一次 { rxtx_it_usart.rx_flag=0;//清除标志位 printf("%s\r\n",rxtx_it_usart.rx_buf);//回显接收到的数据 HAL_UART_Receive_IT(rxtx_it_usart.huart1,rxtx_it_usart.rx_buf,20);//使能接收中断 }
串口调试助手
在USART1下首先将Mode设置为Asynchronous,然后点击两次Add,将串口接收和发送的DMA数据流都添加进去。
DMA数据流的中断使能由CubeMX自动勾选,我们需要勾选使能串口1的中断,中断优先级使用默认值
添加MEMTOMEM
设置时钟
之后生成代码即可
打开工程文件,在main.c中添加以下代码
首先设置发送数据"hello world!"
uint8_t send_data[]=" hello world!\r\n"; //定义发送数据
然后
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)send_data, sizeof(send_data));
仿真结果
串口助手
本次实验其实还不是很难,所以没有设计复杂的函数。通过对stm32中文手册和库函数手册的学习,或通过网络资源学习,都能很好的学会。DMA传输过程不占用CPU资源,可以边传输边运行其他任务,更加高效。
STM32CubeMX之串口使用(中断方式)