完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
之前写了两三篇关于USART+DMA收发的实验, 感觉对USART的收发,已了然于胸(唉,丢人的井底蛙~~~)。
随着经验的积累而发现:利用发送中断,才是UART发送的最优解!! 总结三种发种方式, 并分析其优缺点:
方式一:正常发送 初学STM32时,必用的发送方式。 看看熟悉的代码: // 发送一个字符串 void Usart1_SendString( char* buff ) { while( *buff !=0 ) // 检查是否是字符串结束符 { while( (USART1->SR & 1<<7) == 0 ); // 等待发送缓冲区空闲 USART1->DR = *buff; // 填入发送数据 buff++; // 发送数据指针后移 } } 优点:代码和逻辑都简单,容易理解!新手必备! 缺点:利用while不断检测发送状态+等待,挨个字节发出,其实很费时;如115200波特率,发送100个字节,至少用时8700us!!而且发送期间,中断响应外,整个程序、系统不能干其它事,如假死一般; 方式二:使用DMA发送 先看代码: // 发送一个字符串 void Usart1_Send_DMA(char* charTemp) { u32 num = 0; // 发送的数量,注意发送的单位不是必须8位的 static u8 Flag_DmaTxInit=0; // 用于标记是否已配置DMA发送 char* t=charTemp ; // 用于配合计算发送的数量 while(*t++ !=0) num++; // 计算要发送的数目,这步比较耗时,测试发现每多6个字节,增加1us,单位:8位 while(DMA1_Channel4->CNDTR > 0); // 如果DMA还在进行上次发送,就等待; 得进完成中断清标志,F4不用这么麻烦,发送完后EN自动清零 if( Flag_DmaTxInit == 0) // 是否已进行过USAART_TX的DMA传输配置 { Flag_DmaTxInit = 1; // 设置标记,下次调用本函数就不再进行配置了 USART1 ->CR3 |= 1<<7; // 使能DMA发送 RCC->AHBENR |= 1<<0; // 开启DMA1时钟 [0]DMA1 [1]DMA2 DMA1_Channel4->CCR = 0; // 失能, 清0整个寄存器, DMA必须失能才能配置 DMA1_Channel4->CNDTR = num; // 传输数据量 DMA1_Channel4->CMAR = (u32)charTemp; // 存储器地址 DMA1_Channel4->CPAR = (u32)&USARTx->DR;// 外设地址 DMA1_Channel4->CCR |= 1<<4; // 数据传输方向 0:从外设读 1:从存储器读 DMA1_Channel4->CCR |= 0<<5; // 循环模式 0:不循环 1:循环 DMA1_Channel4->CCR |= 0<<6; // 外设地址非增量模式 DMA1_Channel4->CCR |= 1<<7; // 存储器增量模式 DMA1_Channel4->CCR |= 0<<8; // 外设数据宽度为8位 DMA1_Channel4->CCR |= 0<<10; // 存储器数据宽度8位 DMA1_Channel4->CCR |= 0<<12; // 中等优先级 DMA1_Channel4->CCR |= 0<<14; // 非存储器到存储器模式 } DMA1_Channel4->CCR &= ~((u32)(1<<0)); // 失能,DMA必须失能才能配置 DMA1_Channel4->CNDTR = num; // 传输数据量 DMA1_Channel4->CMAR = (u32)charTemp; // 存储器地址 DMA1_Channel4->CCR |= 1<<0; // 开启DMA传输 } 代码是寄存器编程,精简。但如果使用标准库,或者HAL库,那么代码量会怕吓怕很多人...... 优点:
这种方式,可以说是UART数据发送的最优解!! 先看代码: static u8 TxBuffer[512] ; // 数组大小根据实际数据、发送频率调整 static u8 TxCounter = 0 ; static u8 LastCount = 0 ; // 发送一个字符串 void Usart1_SendIE(u8* buf, u8 cnt) // 指定数据长度,可发送各种数据, 而不仅限于字符串 { for(u8 i=0; i if( (USARTx->CR1 & 1<<7) == 0 ) // 开启 发送缓冲区空置中断, 在USART初始化时,先不要打开空置中断 USARTx->CR1 |= 1<<7; } // 中断服务函数 void USART_IRQHANDLER(void) { if(USART1->SR & 1<<7) // 检查中断来源:发送缓冲区空置——TXE { USART1->DR = TxBuffer[TxCounter++]; // 发送缓冲区填充一个字节 if(TxCounter == LastCount ) // 检查发送是否完成 USART1->CR1 &= ~(1<<7); // 关闭发送缓冲区空置中断 } } 代码量比想象中的要少,而且很有意思~~~。 优点:
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1752 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1611 浏览 1 评论
1052 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1666 浏览 2 评论
1926浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
711浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
560浏览 3评论
583浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
544浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 14:00 , Processed in 0.648172 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号