完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、说明
写本文目的是从 对串口知识了解不清或刚接触的朋友 的角度出发,帮助此类朋友了解掌握串口的配置与使用。 前面介绍三组串口的具体配置,文章最后举一个例子:串口控制小灯。 二、串口的简单介绍 什么是串口? 简单来说就是实现printf(""),getchar()等函数,即实现字符或字符串的接收发送,从而实现通讯。 其中串口又分为:USART(同步异步收发器)——全双工数据交换 和 UART(异步收发器)——只有异步传输功能,本文只介绍三个USART的配置与使用。 三、串口中断功能的流程图(从右到左看) 四、有关管脚的电路原理图介绍 如上图所示:该板子具有三组串口接口(TX为发送引脚,RX为接收引脚),分别对应: RX1/TX1 ——> PA10/PA9 ——> USART1 RX2/TX2 ——> PA3/PA2 ——> USART2 RX3/TX3 ——> PB11/PB10 ——> USART3 [tr]引脚USART1USART2USART3[/tr]
五、代码配置 1.USART1 (1)发送、接收管脚配置和串口配置 void USART1_Config(void) { GPIO_InitTypeDef x; USART_InitTypeDef y; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启管脚PA9,PA10对应的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //开启串口USART1的时钟,注意:**APB2** x.GPIO_Pin=GPIO_Pin_9; x.GPIO_Mode=GPIO_Mode_AF_PP; x.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&x); //配置发送引脚——选择管脚9,模式为复用推挽输出(因为是发送引脚),频率为50MHz,初始化到GPIOA x.GPIO_Pin=GPIO_Pin_10; x.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&x); //配置接收引脚——选择管脚10,模式为浮空输入(因为是接收引脚),输入模式不用配置频率,初始化到GPIOA y.USART_BaudRate=9600; //配置波特率9600/115200等,具体看你的硬件配置要求 y.USART_WordLength=USART_WordLength_8b; //配置数据位8位 y.USART_StopBits=USART_StopBits_1; //配置停止位为1 y.USART_Parity=USART_Parity_No; //奇偶校验位为无校验 y.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //配置硬件控制流选择为无 y.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; //配置串口模式为接收和发送 USART_Init(USART1,&y); //初始化到USART1 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启窗口接收中断(即当发生接收数据或发送数据时将触发对应的中断处理函数) USART_Cmd(USART1,ENABLE); //使能USART1,也就是打开USART1功能 NVIC_Configuration(); //中断优先级配置 }
void NVIC_Configuration() { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置分组为组2 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; //配置中断源为USART1 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //配置主优先级 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //配置子优先级 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //中断使能 NVIC_Init(&NVIC_InitStruct); //初始化NVIC } (3)中断处理函数 void USART1_IRQHandler(void) { u8 res; if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) //若当前USART1的状态为接收 { res= USART_ReceiveData(USART1); //读取此时接收的数据 USART_SendData(USART1,res); //将数据重新发回去,用于告诉它接收成功 } } (4)重定向收发函数(在 keil 的 C 标准函数中类似 printf 等函数并没有实现其底层,程序开发者需要重定向其中的 fgets 与 fputs 函数后可使用 printf、scanf、gets、puts 等标准函数,记得加#include "stdio.h"哦) #include "stdio.h" int fputc(int ch,FILE *f) { USART_SendData(USART1,(uint8_t)ch); //发送一个字符 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); //直到发送完毕 return (ch); } int fgetc(FILE *f) { while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET); //直到接收完毕 return (int)USART_ReceiveData(USART1); } (5)最后主函数 int main(void) { USART1_Config(); while(1); } 这样一个完整的串口配置使用就实现了哦!!! 接下来同样的步骤,来用其他两组串口也实现该功能吧 2.USART2 (1)发送、接收管脚配置和串口配置 void USART2_Config(void) { GPIO_InitTypeDef x; USART_InitTypeDef y; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //注意**APB1**,**USART2** x.GPIO_Pin=GPIO_Pin_2; x.GPIO_Mode=GPIO_Mode_AF_PP; x.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&x); x.GPIO_Pin=GPIO_Pin_3; x.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&x); y.USART_BaudRate=9600; y.USART_WordLength=USART_WordLength_8b; y.USART_StopBits=USART_StopBits_1; y.USART_Parity=USART_Parity_No; y.USART_HardwareFlowControl=USART_HardwareFlowControl_None; y.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; USART_Init(USART2,&y); USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); USART_Cmd(USART2,ENABLE); NVIC_Configuration(); } (2)配置中断优先级 void NVIC_Configuration() { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn; //注意:**USART2_IRQn** NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); } (3)中断处理函数 void USART2_IRQHandler(void) //注意:**USART2_IRQHandler** { u8 res; if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET) { res= USART_ReceiveData(USART2); USART_SendData(USART2,res); } } (4)重定向收发函数(记得加#include "stdio.h"哦) #include "stdio.h" int fputc(int ch,FILE *f) { USART_SendData(USART2,(uint8_t)ch); while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET); return (ch); } int fgetc(FILE *f) { while(USART_GetFlagStatus(USART2,USART_FLAG_RXNE)==RESET); return (int)USART_ReceiveData(USART2); } (5)最后主函数 int main(void) { USART2_Config(); while(1); } 2.USART3 (1)发送、接收管脚配置和串口配置 void USART3_Config(void) { GPIO_InitTypeDef x; USART_InitTypeDef y; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //注意:**GPIOB** RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //注意:**APB1**,**USART3** x.GPIO_Pin=GPIO_Pin_10; x.GPIO_Mode=GPIO_Mode_AF_PP; x.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&x); //注意:**GPIOB** x.GPIO_Pin=GPIO_Pin_11; x.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB,&x); //注意:**GPIOB** y.USART_BaudRate=9600; y.USART_WordLength=USART_WordLength_8b; y.USART_StopBits=USART_StopBits_1; y.USART_Parity=USART_Parity_No; y.USART_HardwareFlowControl=USART_HardwareFlowControl_None; y.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; USART_Init(USART3,&y); USART_ITConfig(USART3,USART_IT_RXNE,ENABLE); USART_Cmd(USART3,ENABLE); NVIC_Configuration(); } (2)配置中断优先级 void NVIC_Configuration() { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn; //注意:**USART3_IRQn** NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; } (3)中断处理函数 void USART3_IRQHandler(void) //注意:**USART3_IRQHandler** { u8 res; if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET) { res= USART_ReceiveData(USART3); USART_SendData(USART3,res); } } (4)重定向收发函数(记得加#include "stdio.h"哦) #include "stdio.h" int fputc(int ch,FILE *f) { USART_SendData(USART3,(uint8_t)ch); while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET); return (ch); } int fgetc(FILE *f) { while(USART_GetFlagStatus(USART3,USART_FLAG_RXNE)==RESET); return (int)USART_ReceiveData(USART3); } (5)最后主函数 int main(void) { USART3_Config(); while(1); } 六、最后来个串口控制小灯例子 (1)配置串口(上面三组随便选一组,这里以组1-PA9,PA10为例) (2)初始化小灯(我的STM32控制LED灯的管脚为PC13) void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStruct); } (3)小灯控制函数 void LED_G(uint8_t n) //LED_G(0): 灯亮 LED_G(1):灯灭 { if(n) GPIO_SetBits(GPIOC, GPIO_Pin_13); else GPIO_ResetBits(GPIOC, GPIO_Pin_13); } (4)修改主函数 #include "stm32f10x.h" int main(void) { USART_Config(); LED_GPIO_Config(); while(1); } (5)修改串口中断函数 void USART1_IRQHandler(void) //如果串口发送‘0’则灯亮,(若其他数据)否则灯灭 { u8 res; if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) { res= USART_ReceiveData(USART1); USART_SendData(USART1,res); if(res=='0') { LED_G(0); } else { LED_G(1); } } } |
|||
|
|||
只有小组成员才能发言,加入小组>>
3318 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9063 浏览 16 评论
4088 浏览 18 评论
1182浏览 3评论
608浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
600浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 20:36 , Processed in 1.482836 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号