完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
今天写一下关于串口通信的内容,实现的是串口助手向单片机发送信息,并显示到LCD上。
明确几点:
可以看到有两个串口,那么我们再来分别看一下这两个串口在电路图中是怎么连接的: 我们可以看到串口1的通信引脚是接在RS232的接口上的,这种接口一般不是很常用,我们经常使用的接口应该都是USB接口,所以我们不用串口1来进行通信。再来看一下串口2: 串口2连接USB接口,所以我们利用串口2(USART2)来进行串口通信,那么我们就用到PA2(数据发送引脚)和PA3(数据接收引脚)这两个引脚。 下面我们来看一下USART的配置流程:使能时钟+配置相关引脚->配置时钟相关参数->时钟中断配置->时钟使能+中断使能 我们来按照步骤一步一步配置:
//使能GPIOA和USART2时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE); //RXD-PA3 设置为浮空模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); //TXD-PA2 设置为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART2的配置 USART_InitStructure.USART_BaudRate = 9600;//设置波特率为9600 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据长度为8位 USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位数为1 USART_InitStructure.USART_Parity = USART_Parity_No;//不设置奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//禁用硬件流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//串口模式选择发送使能和接收使能 USART_Init(USART2, &USART_InitStructure);//初始化USART2 做几点说明:
//USART2的中断优先级配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//选择USART2通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道 NVIC_Init(&NVIC_InitStructure);//调用初始化函数
USART_Cmd(USART2, ENABLE);//开启USART2 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启USART2接收中断 这里要注意一点:这里只能使能串口接收中断!!!发送中断在数据发送前使能,数据发送完毕后就要关闭!!! 总的串口初始化程序: void USART2_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; //开启GPIOA和USART2时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE); //USART2的中断优先级配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//选择USART2通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道 NVIC_Init(&NVIC_InitStructure);//调用初始化函数 //RXD-PA3 设置为浮空模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); //TXD-PA2 设置为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //USART2的配置 USART_InitStructure.USART_BaudRate = 9600;//设置波特率为9600 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据长度为8位 USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位数为1 USART_InitStructure.USART_Parity = USART_Parity_No;//不设置奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//禁用硬件流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//串口模式选择发送使能和接收使能 USART_Init(USART2, &USART_InitStructure);//初始化USART2 USART_Cmd(USART2, ENABLE);//开启USART2 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启USART2接收中断 } 初始化串口之后,我们还要写一个串口发送数据的函数: void USART2_SendString(u8 *str) { u8 index = 0; while(str[index++] != 0) { USART_SendData(USART2, str[index-1]);//发送一个字节的数据,注意这里是index-1!,如果是index则不能显示第一个字符!!! while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == 0);//数据发送结束(TXE为1)则跳出循环 index++; } } 这里涉及到了标志位的问题,我们怎么判断一帧数据发送完了呢? 我们先来了解一下发送数据的流程:内部总线->TDR数据寄存器->发送移位寄存器->TXD引脚输出;这里的发送移位寄存器可以理解为一个数据的中转站,一帧的数据会先由数据寄存器送达中转站,然后再输出,这时我们的TDR寄存器是空的,那么就会产生一个标志位(TXE = 1),表明我们可以发送下一帧的数据,这个TXE就是硬件设置的TXD为空的标志,我们也可以看一下这个引脚的功能: 读数据的流程与发送数据的流程相类似,用到的标志位是RXNE,从下面的图片中我们可以看到当RXNE为1时,表示数据接收到了,那么我们在写接收数据的函数时肯定也是在这种情况下进行操作的; 明白了上面的内容,我们也就能理解下面这行代码的意思了: while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == 0);//数据发送结束(TXE为1)则跳出循环 当TXE为0时,表明这一帧数据没有发送完,那么我们就一直在while循环内执行,直到这一帧数据完全发送到移位寄存器(即TXE = 1); 发送完数据我们肯定还要接收数据啊,接收数据是利用串口中断来接收的,所以我们还要在stm32f10x_it.c文件中编写一个USART中断服务函数: NOTICE!!!stm32的中断服务函数是有特定的名称的,我们编写的中断服务函数必须与这个名称一致才可以,否则就会报错!!!我们用到的是串口2,所以要编写串口2的中断服务函数:(void USART2_IRQHandler(void)) void USART2_IRQHandler(void) { u16 tmp; if(USART_GetITStatus(USART2, USART_IT_RXNE) == 1)//检测接收中断标志位,RXNE为1表示接收到了数据 { USART_ClearITPendingBit(USART2, USART_IT_RXNE);//清除中断标志位(即清除RXNE) tmp = USART_ReceiveData(USART2);//读取串口2的数据 if(tmp == 'n')//‘/n’表示本次读取结束 { RxdBuf[RxdCnt-1] = 0;//避免r显示在LCD发生的乱码 RxdCnt = 0;//读取结束清RxdCnt RxdOver = 1;//本次数据读取结束标志置1 USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//接收完毕后关闭,防止处理过程发生干扰。 } else { RxdBuf[RxdCnt++] = tmp;//将读取到的数据存到RXDBuf中 } } } 主函数: #include "stm32f10x.h" #include "lcd.h" #include "usart2.h" u32 TimingDelay = 0; u8 RxdCnt = 0;//用来计数读取到的字节数 u8 RxdOver = 0;//读取数据是否结束:0-未结束,1-结束 u8 RxdBuf[20];//存储读到的数据 void Delay_Ms(u32 nTime); //Main Body int main(void) { u8 i; STM3210B_LCD_Init(); LCD_Clear(Blue); LCD_SetBackColor(Blue); LCD_SetTextColor(White); SysTick_Config(SystemCoreClock/1000); USART2_Init();//串口初始化 while(1) { if(RxdOver) { RxdOver = 0; LCD_ClearLine(Line5);//清除LCD的对应行 LCD_DisplayStringLine(Line5, RxdBuf); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//接收的数据处理完毕后打开接收中断 for(i=0; i<20; i++)//清空缓冲区 RxdBuf = 0; } } } // void Delay_Ms(u32 nTime) { TimingDelay = nTime; while(TimingDelay != 0); } 这段代码实现的功能是:利用串口助手向单片机发送数据,数据可显示到LCD上,关于LCD的部分,我是直接用蓝桥嵌入式里面的液晶显示例程来建工程的,emmm,LCD的部分我暂时还没有学到。 一些错误: 一直搜索不到串口怎么办? 右键点击: 选择更新设备程序: 选择自动搜索更新,ok |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1780 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1081 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1679 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
556浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 14:36 , Processed in 0.839361 second(s), Total 49, Slave 42 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号