Ⅰ-中断方式点灯
中断
中断通常被定义为一个事件,该事件能够改变处理器执行指令的顺序。这样的事件与 CPU 芯片内外部硬件电路产生的电信号相对应。中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。 我们可以通过中断使处理器转而去优先运行正常控制流之外的代码。
中断分为同步中断和异步中断: 同步中断:同步中断是当指令执行时由控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后 CPU 才会发出中断。 异步中断:异步中断是由其他硬件设备依照 CPU时钟信号随机产生的。 通常所说的中断指的是异步中断,我们将同步中断称为异常。(异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的) 硬中断:通过处理器中断信号线产生的中断 软中断:通过非法指令或特殊指令触发的中断
中断的优先级 多个中断同时出现时,处理器先响应高优先级的中断 低优先级中断的ISR执行时,可以被高优先级中断再次打断 ISR比App Code拥有更高的执行优先级
1.创建STM32CubeMX工程LED
开发板以STM32F103ZE为例 1.设置指示灯LED引脚PB5,设置引脚模式为输出模式GPIO_Output。 设置按键引脚PE8,设置引脚为外部中断功能,PE8与外部中断线EXTI8连接GPIO_EXTI8 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8e4a31a58cf6400fab572251f6e9de31.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/c7896915bcb242779f8776ab8500c3d6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/03ee1350e8584cf4aed49a5e96b7826c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_17,color_FFFFFF,t_70,g_se,x_16) 2. PE8对应的外部中断线 点击Enabled ![在这里插入图片描述](https://img-blog.csdnimg.cn/2acfb57573754fa8a94ac7d04b5c0cab.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_19,color_FFFFFF,t_70,g_se,x_16)
3.命名 修改 生成代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/02a6b45a555c4a83825d028a76ee7436.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) OpenProject ![在这里插入图片描述](https://img-blog.csdnimg.cn/1ccb3f7418384e9285e8939ed4c409ba.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_12,color_FFFFFF,t_70,g_se,x_16)
2.keil代码修改LED
1.找到HAL_GPIO_EXTI_Callback 并重写 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0cea77f279d54cfd8fdfb7221df70ddc.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if( GPIO_Pin == F8_EXTI_Pin)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
}
2build debug -run 烧录到开发板中 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b93435cf1c3c462f9b796033d9f0ab6e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16)
3.结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/287ab881653045afbdf73a96b6fb3a33.gif)
Ⅱ-中断方式串口通信
1.创建STM32CubeMX工程USART
开发板STM32F407ZE ![在这里插入图片描述](https://img-blog.csdnimg.cn/9b7115b32a61403a83fec12f8f2bf626.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) 1.设置RCC ![在这里插入图片描述](https://img-blog.csdnimg.cn/33276c39860546bfaa77ef5b20a52bea.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) 2.设置串口
mode设置为异步通信 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ce25fe9d113e484f9cfce183c6e0c82a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/8b00cbe9cee841108404313010645e46.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_17,color_FFFFFF,t_70,g_se,x_16) 3.设置时钟 ![在这里插入图片描述](https://img-blog.csdnimg.cn/62014a8bcfbe43b793da16f97bcf284f.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) 4.命名 修改 生成代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8cc15ee5681c4b71a69f1a5d1966cfd9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16)
2.keil代码修改USART
1.usart.c添加
#if 1
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0x0001);
return ch;
}
#endif
![在这里插入图片描述](https://img-blog.csdnimg.cn/638db1b5da4b4071862e0e0e7490fee9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_14,color_FFFFFF,t_70,g_se,x_16) 2.main函数while循环中添加
printf("Hello windows!\r\n");
HAL_Delay(500);
![在这里插入图片描述](https://img-blog.csdnimg.cn/00c780b86b904b17a166758ee8f7beef.png) 3.添加定义接收串口数据
uint8_t aRxBuffer;
uint8_t Uart1_RxBuff[256];
uint8_t Uart1_Rx_Cnt = 0;
uint8_t cAlmStr[] = "数据溢出(大于256)\r\n";
4.添加开启接收中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
5.添加中断回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
if(Uart1_Rx_Cnt >= 255)
{
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer;
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 *)&aRxBuffer, 1);
}
3.结果
发送stop时中断再次发送回到循环
![在这里插入图片描述](https://img-blog.csdnimg.cn/50af2986af4c484ba7f1e2d331c820d8.png)
Ⅲ-DMA向上位机发送数据
DMA
DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。
DMA的主要特征 ·每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发,这些功能通过软件来配置。 ·在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)。 ·独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。 ·支持循环的缓冲器管理。 ·每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。 ·存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输。 ·闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。 ·可编程的数据传输数目:最大为65535(0xFFFF)。
1.创建STM32CubeMX工程
开发板STM32F407ZE ![在这里插入图片描述](https://img-blog.csdnimg.cn/10d41b3d4be14a32a852efdd4d425f4d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) 设置RCC ![在这里插入图片描述](https://img-blog.csdnimg.cn/886859eb550d48ce93ed4385613b66c9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) 设置串口 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c0b316f98d4f4b47a5b46a786d225a14.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) DMA设置 ![在这里插入图片描述](https://img-blog.csdnimg.cn/38d55f842bc244919a7695805a034a50.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/b4c2b6f0278a42a2a20d6347bf47dd80.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16) 时钟设置 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7598e0ed74884ddc8ca212ea5b8a3cee.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rC46L-c54ixbWFp,size_20,color_FFFFFF,t_70,g_se,x_16)
2.keil代码修改
main.c中添加
uint8_t Senbuff[] = "Hello windows!";
while中添加
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
3.结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/1c2a239f743a4818b67c64b64e1547e9.png)
小结
本文通过中断重写了LED和串口通信并用DMA重新了串口通信
链接
中断亮灯 基于STM32F407中断方式实现串口通信 DMA原理介绍 DMA原理,步骤超细详解,一文看懂DMA
|