完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、实验任务
用串口助手通过串口1向单片机发送数据,并将单片机接收到的数据通过串口返回到串口助手。主要任务如下: (1)编写串口初始化函数; (2)编写串口中断服务函数; (3)编写实现功能的main函数。 二、硬件设计 实验中用到的串口 1 与 USB 串口并没有在 PCB 上连接在一起,需要通过跳线帽来连接一下。这里我们把 P4 的 RXD 和 TXD 用跳线帽与 PA9 和 PA10 连接起来。 三、软件设计 1.uart_init 函数 //初始化 IO 串口 1 //bound:波特率 void uart_init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //①串口时钟使能,GPIO 时钟使能,复用时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOA, ENABLE); //使能 USART1,GPIOA 时钟 //②串口复位 USART_DeInit(USART1); //复位串口 1 //③GPIO 端口模式设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //ISART1_TX PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX PA.10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10 //④串口参数初始化 USART_InitStructure.USART_BaudRate = bound; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为 8 位 USART_InitStructure.USART_StopBits = USART_StopBits_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(USART1, &USART_InitStructure); //初始化串口 #if EN_USART1_RX //如果使能了接收 //⑤初始化 NVIC NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级 3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能 NVIC_Init(&NVIC_InitStructure); //中断优先级初始化 //⑤开启中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断 #endif //⑥使能串口 USART_Cmd(USART1, ENABLE); //使能串口 } 从该代码可以看出,其初始化串口的过程,我们用标号①~⑥标示了顺序: ① 串口时钟使能,GPIO 时钟使能 ② 串口复位 ③ GPIO 端口模式设置 ④ 串口参数初始化 ⑤ 初始化 NVIC 并且开启中断 ⑥ 使能串口 配置全双工的串口 1,那么 TX(PA9)管脚需要配置为推挽复用输出,RX(PA10)管脚配置为浮空输入或者带上拉输入。模式配置参考下面表格: 使用到了串口的中断接收,必须在 usart.h 里面设置EN_USART1_RX 为 1(默认设置就是 1 ) ,该函数才会配置中断使能,以及开启串口 1 的NVIC 中断。这里我们把串口 1 中断放在组 2,优先级设置为组 2 里面的最低。从该代码可以看出,其初始化串口的过程,和我们前面介绍的一致。先计算得到USART1-》BRR 的内容。然后开始初始化串口引脚,接着把 USART1 复位,然之后设置波特率和奇偶校验等。 2.中断服务函数 USART1_IRQHandler void USART1_IRQHandler(void) //串口 1 中断服务程序 { u8 Res; #if SYSTEM_SUPPORT_OS //如果 SYSTEM_SUPPORT_OS 为真,则需要支持 OS OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是 0x0d 0x0a 结尾) { Res =USART_ReceiveData(USART1);//(USART1-》DR); //读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收到了 0x0d { if(Res!=0x0a) USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到 0X0D { if(Res==0x0d) USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA》(USART_REC_LEN-1)) USART_RX_STA=0; //接收数据错误,重新开始接收 } } } } #if SYSTEM_SUPPORT_OS //如果 SYSTEM_SUPPORT_OS 为真,则需要支持 OS OSIntExit(); #endif } void USART1_IRQHandler(void)函数是串口 1 的中断响应函数,当串口 1 发生了相应的中断后,就会跳到该函数执行。 函数体里面通过函数: if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 判断是否接受中断,如果是串口接受中断,则读取串口接受到的数据: Res =USART_ReceiveData(USART1);//(USART1-》DR); //读取接收到的数据 读到数据后接下来就对数据进行分析。 这 里 我 们 设 计 了 一 个接 收 协 议 : 通 过 这 个 函 数 , 配 合 一 个 数 组USART_RX_BUF[],一个接收状态寄存器 USART_RX_STA(此寄存器其实就是一个全局变量,由作者自行添加。由于它起到类似寄存器的功能,这里暂且称之为寄存器)实现对串口数据的接收管理。USART_RX_BUF 的大小由 USART_REC_LEN 定义,也就是一次接收的数据最大不能超过 USART_REC_LEN 个字节。USART_RX_STA 是一个接收状态寄存器其各的定义如下: 当接收到从电脑发过来的数据,把接收到的数据保存在 USART_RX_BUF 中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的表示由 2 个字节组成:0X0D 和 0X0A)的第一个字节 0X0D 时,计数器将不再增加,等待0X0A 的到来,而如果 0X0A 没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到 0X0A,则标记 USART_RX_STA 的第 15 位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到 0X0D,那么在接收数据超过 USART_REC_LEN 的时候,则会丢弃前面的数据,重新接收。 3.main.c函数 #include “sys.h” #include “usart.h” #include “delay.h” #include “led.h” int main(void) { u8 t; u8 len; u16 times=0; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组 uart_init(9600); //串口初始化为 9600 LED_Init(); //初始化与 LED 连接的硬件接口 while(1) { if(USART_RX_STA&0x8000) { len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 printf(“rn 您发送的消息为:rn”); for(t=0;t《len;t++) { USART1-》DR=USART_RX_BUF[t]; while((USART1-》SR&0X40)==0);//等待发送结束 } printf(“rnrn”);//插入换行 USART_RX_STA=0; } else { times++; if(times%5000==0) { printf(“r串口实验rn”); } if(times%200==0)printf(“请输入数据,以回车键结束rn”); if(times%30==0)LED0=!LED0;//闪烁 LED,提示系统正在运行。 delay_ms(10); } } } NVIC_PriorityGroupConfig ()函数设置中断分组号为 2,也就是 2 位抢占优先级和 2 位子优先级。 USART_SendData(USART1, USART_RX_BUF[t]); //向串口 1 发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); 第一句,其实就是发送一个字节到串口。第二句呢,就是我们在我们发送一个数据到串口之后,要检测这个数据是否已经被发送完成了。USART_FLAG_TC 是宏定义的数据发送完成标识符。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1758 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1613 浏览 1 评论
1055 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1670 浏览 2 评论
1932浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
722浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
564浏览 3评论
590浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
548浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-20 08:24 , Processed in 0.893576 second(s), Total 75, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号