完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、外部中断,实现LED的闪亮与熄灭 1.创建工程 然后自动生成程序。 2.编译与写程序 以看到生成的中断服务函数 void EXTI1_IRQHandler(void) 可以看到该函数又调用了HAL_GPIO_EXTI_IRQHandler(),于是继续跳转到下一函数 可以看到在这之中调用了HAL_GPIO_EXTI_Callback(),接下来的函数可以看到是_weak开头,则需要用户自己写函数。 此时到main.c中书写callback程序,用到的库函数是HAL_GPIO_TogglePin(),该函数的作用是翻转电平,即中断一产生,则翻转一次电平。 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ {HAL_GPIO_TogglePin(led1_GPIO_Port,led1_Pin);}} 接着进行编译。 3.烧录 通电下将boot0置0,然后再次reset后可运行 4.实验结果 此处因为stm32c8t6没有按键,因此选择使用杜邦线代替开关,每接触一次接地,则产生一次中断 二、串口中断实现串口通信 1.创建工程 RCC和SYS和CLOCK设置如上面一样 下面设置串口USART1,在MODE下选择Asynchronous(异步通信模式),并且使得USART1中断使能 接着就可以直接生成工程了 2.重定向printf和scanf #include
/** * 函数功能: 重定向c库函数printf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff); return ch; } /** * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ int fgetc(FILE *f) { uint8_t ch = 0; HAL_UART_Receive(&huart1, &ch, 1, 0xffff); return ch; } 在main.c中添加 #define RXBUFFERSIZE 256char RxBuffer[RXBUFFERSIZE]; printf("hello worldn"); HAL_Delay(1000); 在target勾选Use MicroLIB,需要调用微型库 3.运行结果 4.UART接收中断 具体流程:
代码实现 并在main.c中添加下列定义: #include #define RXBUFFERSIZE 256 //最大接收字节数 char RxBuffer[RXBUFFERSIZE]; //接收数据 在main()主函数中,调用一次接收中断函数 /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart1, RxBuffer, 1); /* USER CODE END 2 */ 在main.c下方添加中断回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance==USART1) { HAL_UART_Transmit(&huart1,RxBuffer,1,0xff); } HAL_UART_Receive_IT(&huart1, RxBuffer, 1); } 实验成果 可以看到串口回显。 三、串口DMA接收发数据 1.创建工程 其余设置参考上面串口设置 以下为不同点 进入DMA Settings 点击add,选择USART_RX USART_TX 传输速率设置为中速 DMA传输模式为正常模式 DMA内存地址自增,每次增加一个Byte(字节) 右侧点击System Core 点击DMA 点击add添加MENTOMEN Normal:正常模式 当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次 DMA指针递增设置 Increment Address:地址指针递增(上方有介绍)。 左侧Src Memory 表示外设地址寄存器 功能:设置传输数据的时候外设地址是不变还是递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节, 右侧Dst Memory 表示内存地址寄存器 功能:设置传输数据时候内存地址是否递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节, 这个Src Memory一样,只不过针对的是内存。 然后即可生成工程。 2.测试例程1 在main.C中添加: /* USER CODE BEGIN Init */ uint8_t Senbuff[] = "HELLO WORLD"; //定义数据发送数组 /* USER CODE END Init */ while循环: while (1) { /* USER CODE END WHILE */ HAL_UART_Transmit_DMA(&huart1, Senbuff, sizeof(Senbuff)); HAL_Delay(1000); /* USER CODE BEGIN 3 */ } 3.测试结果 4.测试例程2 STM32 IDLE 接收空闲中断 STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断 代码: uart.c volatile uint8_t rx_len = 0; //接收一帧数据的长度 volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志 uint8_t rx_buffer[100]={0}; //接收数据缓存数组 /* USER CODE BEGIN USART1_Init 2 */ __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断 //DMA接收函数,此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE); /* USER CODE END USART1_Init 2 */ uart.h extern UART_HandleTypeDef huart1;extern DMA_HandleTypeDef hdma_usart1_rx;extern DMA_HandleTypeDef hdma_usart1_tx;/* USER CODE BEGIN Private defines */ #define BUFFER_SIZE 100 extern volatile uint8_t rx_len ; //接收一帧数据的长度extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志extern uint8_t rx_buffer[100]; //接收数据缓存数组 工程里没有.h文件,需要在文件夹里寻找 main.c extern UART_HandleTypeDef huart1; extern DMA_HandleTypeDef hdma_usart1_rx; extern DMA_HandleTypeDef hdma_usart1_tx; /* USER CODE BEGIN Private defines */ #define BUFFER_SIZE 100 extern volatile uint8_t rx_len ; //接收一帧数据的长度 extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志 extern uint8_t rx_buffer[100]; //接收数据缓存数组 这里需要定义在main函数前面,否则在main函数里调用会报错,也可以在main之前先声明函数。 while循环 /* ********************************************************************************************************* * 函 数 名: DMA_Usart_Send * 功能说明: 串口发送功能函数 * 形 参: buf,len * 返 回 值: 无 ********************************************************************************************************* */ void DMA_Usart_Send(uint8_t *buf,uint8_t len)//串口发送封装 { if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数 { Error_Handler(); } } /* ********************************************************************************************************* * 函 数 名: DMA_Usart1_Read * 功能说明: 串口接收功能函数 * 形 参: Data,len * 返 回 值: 无 ********************************************************************************************************* */ void DMA_Usart1_Read(uint8_t *Data,uint8_t len)//串口接收封装 { HAL_UART_Receive_DMA(&huart1,Data,len);//重新打开DMA接收 } 5. 测试程序 四、总结 通过这次实验发现中断与串口DMA通信,可以提高程序的运行效率,DMA可以直接访问存储器,没有经过CPU,CPU负担减轻,熟悉了串口通信的基本函数和DMA通信的基本函数。 |
|
|
|
只有小组成员才能发言,加入小组>>
3309 浏览 9 评论
2988 浏览 16 评论
3490 浏览 1 评论
9050 浏览 16 评论
4084 浏览 18 评论
1169浏览 3评论
602浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
593浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2330浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-19 18:03 , Processed in 1.266548 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号