目录
一、中断
1.1、中断介绍
外部中断通常是 GPIO 的电平跳变引起的中断。在 stm32 中,每一个 GPIO 都可以作为外部中断的触发源。
外部中断支持 GPIO 的三种电平跳变模式。
1.上升沿中断:当 GPIO 的电平从低电平跳变成高电平时,引发外部中断。
2.下降沿中断:当 GPIO 的电平从高电平跳变成低电平时,引发外部中断。
3.上升沿和下降沿中断:当 GPIO 的电平从低电平跳变成高电平和从高电平跳变成低电平时,都能引发外部中断。
1.2、中断级数比较
已经有中断在工作。根据抢占优先级决定,新来的中断打不打断原有中断,打断就发生中断嵌套,不打断就挂起等着。
中断都在挂起等待的状态,先按抢占优先级排序,抢占优先级高的先行,抢占优先级相同,就按子优先级排序,子优先级高的先行,子优先级还相同,那就按IRQ编号小的先行
抢占优先级>子优先级>IRQ编号
二、中断实现LED
2.1、工程建立
选择芯片,进行芯片相应配置
我这里直接选择STM32F103C8芯片。
在左侧芯片上进行输出管脚以及开关管脚选择配置
进行LED_KEY配置
接下来便是文件的保存地址的选择,这里就不再说明。直接生成工程代码。
2.2、代码编写及结果展示
HAL_GPIO_EXTI_Callback
每当产生外部中断时,程序首先会进入外部中断服务函数。在 stm32f4xx_it.c 中,可以找到函数 EXTI0_IRQHandler,它通过调用函数HAL_GPIO_EXTI_IRQHandler 对中断类型进行判断,并对涉及中断的寄存器进行处理,在处理完成后,它将调用中断回调函数HAL_GPIO_EXTI_Callback,在中断回调函数中编写在此次中断中需要执行的功能。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
while(1)
{
GPIO_PinState B1_pin = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
switch (GPIO_Pin)
{
case GPIO_PIN_1:
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, B1_pin);
break;
}
}
}
编译运行,并将生成的HEX文件烧录到芯片。
结果展示:
三、中断实现串口通信
3.1、工程建立
打开STM32CubeMX,选择相应的芯片型号,并配置调试信息为:Serial Wire
配置RCC主频,选择外部高速晶振(HSE):Crystal/Ceramic Resonator(译文:水晶/陶瓷谐振器)
配置USART1:选择异步通信模式-使能USART1中断
3.2、写入代码
首先自己定义一个数组的长度用来放置所传输的数据:
uint8_t OT_RxBuffer;
uint8_t Uart1_RxBuff[10000];
uint8_t Uart1_Rx_Cnt = 0;
编写接受函数
HAL_UART_Receive_IT(&huart1, (uint8_t *)&OT_RxBuffer, 1);
使能函数以及发送函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
Uart1_RxBuff[Uart1_Rx_Cnt++] = OT_RxBuffer; //??????
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D))
{
HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF);
Uart1_Rx_Cnt = 0;
//memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&OT_RxBuffer, 1);
}
3.3、调试运行并显示结果
在编译完成后,将hex文件烧录到stm32最小板中,利用野火串口调试助手进行演示。
【STM32CubeMX】HAL库中断方式UART串口通信_cayloon的博客-CSDN博客_hal库串口中断
四、利用DMA实现串口通信
DMA介绍:
DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
DMA定义:
DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。DMA传输方式
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:外设到内存
内存到外设
内存到内存
外设到外设
DMA传输参数
我们知道,数据传输,首先需要的是1 数据的源地址 2 数据传输位置的目标地址 ,3 传递数据多少的数据传输量 ,4 进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。
也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。
4.1、Cube工程建立
打开CubeMX软件,选择芯片(我选择的为f103c8,这里就不再多说明)
设置RCC——设置高速外部时钟HSE 选择外部时钟源
设置串口
1点击USATR1
2设置MODE为异步通信(Asynchronous)
3基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1 接收和发送都使能
4GPIO引脚自动设置 USART1_RX/USART_TX
5 NVIC Settings 一栏使能接收中断
DMA设置
根据DMA通道预览可以知道,我们用的USART1 的TX RX 分别对应DMA1 的通道4和通道5
点击DMASettings 点击 Add 添加通道
选择USART_RX USART_TX 传输速率设置为中速
DMA传输模式为正常模式
DMA内存地址自增,每次增加一个Byte(字节)
DMA基础设置
右侧点击System Core 点击DMA
关于上面的四中传输方式,这里不做过多说明,后面会给与参考链接,有兴趣的同学可以去看看。
时钟源设置
将时钟源配置好过后,一个完整的DMA工程差不多就配置好了,后面的保存工程以及生成c语言代码我就不做仔细说明了。
4.2、编写代码
在main.C中添加:
/* USER CODE BEGIN Init */
uint8_t Senbuff[] = "Hello windows\n"; //定义数据发送数组
/* USER CODE END Init */
while循环:
while (1)
{
/* USER CODE END WHILE */
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
4.3、测试结果显示
将编译生成的Hex文件烧录至芯片,在通过串口助手显示得出:
五、总结
在本次实验中,我们可以明显的发现利用CubeMX软件可以很大程度上减少我们的代码编写过程,在进行编写时,只需要找出要用到的函数,然后进行调用就能完美的实现结果。其次,对于中断函数的实现,通过与查询方式进行对比,发现中断较麻烦一点,但相比于查询,中断方式的时间是十分准确的,因此,当我们需要准确的时间时,便可以采用这个中断方式。
六、参考资料
STM32新手必看 简单几步用cubeMX完成按键的外部中断控制灯的亮灭(STM32F103RCT)_ZCHHHHHHH12的博客-CSDN博客_stm32外部中断控制led灯亮灭
STM32之中断控制LED灯_Baker的博客-CSDN博客
【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)_Z小旋-CSDN博客_hal库串口dma