完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1. 处理器与外部设备通信的两种方式
1.1 并行通信,传输原理:数据各个位同时传输。优点:速度快。缺点:占用引脚资源多。 1.2 串行通信,传输原理:数据按位顺序传输。优点:占用引脚资源少。缺点:速度相对较慢。 2. 串行通信(按照数据传送方向可分为) 2.1 单工:数据传输只支持数据在一个方向上传输(图a); 2.2 半双工:允许数据在两个方向上传输,但在某一时刻,只允许数据在一个方向上传输,实际上是一种切换方向的单工通信(图b); 2.3 全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力(图c)。 3. 串行通信的通信方式 3.1 同步通信:带时钟同步信号传输,包括SPI,IIC通信接口; 3.2 异步通信:不带时钟同步信号,包括UART(通用异步收发器,双方需事先约定好波特率),单总线。 4. 常见的串行通讯接口 5. STM32的串口通信接口 5.1 UART:通用异步收发器; 5.2 USART:通用同步异步收发器。 备注:大容量STM32F10x系列芯片,包含3个USART和2个UART。 6. UART异步通信方式引脚连接方法 6.1 RXD:数据输入引脚。数据接受; 6.2 TXD:数据发送引脚。数据发送。 6.3 开发版上的串口引脚如下表所示: 7. UART异步通信方式特点 7.1 全双工异步通信; 7.2 分数波特率发生器系统,提供精确的波特率。发送和接受共用的可编程波特率,最高可达4.5Mbits/s; 7.3 可编程的数据字长度(8位或者9位); 7.4 可配置的停止位(支持1或者2位停止位); 7.5 可配置的使用DMA多缓冲器通信; 7.6 单独的发送器和接收器使能位; 7.7 检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志; 7.8 多个带标志的中断源。触发中断; 7.9 其他:校验控制,四个错误检测标志。 8. 串口通信过程 9. STM32串口异步通信需要定义的参数 9.1 起始位; 9.2 数据位(8位或者9位); 9.3 奇偶校验位(第9位); 9.4 停止位(1,15,2位); 9.5 波特率设置。 10. STM32串口框图 10.1 对于大容量的STM32F10x芯片,有5个串口,串口1时钟来源PCLK2,串口2~4时钟来源PCLK1。 11. 常用的串口相关寄存器 11.1 USART_SR状态寄存器(串口通信的状态位); 11.2 USART_DR数据寄存器(读写都通过该寄存器); 11.3 USART_BRR波特率寄存器。 12. 串口操作相关库函数 void USART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能// void USART_Cmd(); //使能串口// void USART_ITConfig(); //使能相关中断// void USART_SendData(); //发送数据到串口,针对DR寄存器// uint16_t USART_ReceiveData(); //接受数据,从DR读取接受到的数据,针对DR寄存器// FlagStatus USART_GetFlagStatus(); //获取状态标志位,针对SR寄存器// void USART_ClearFlag(); //清除状态标志位,针对SR寄存器// ITStatus USART_GetITStatus(); //获取中断状态标志位,针对SR寄存器// void USART_ClearITPendingBit(); //清除中断状态标志位,针对SR寄存器// 13. 串口常用寄存器解读 13.1 状态寄存器(USART_SR) FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); 13.2 数据寄存器(USART_DR) void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); uint16_t USART_ReceiveData(USART_TypeDef* USARTx); 13.3 波特比率寄存器(USART_BRR) void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 14. 波特率计算方法 15. 串口配置一般步骤 15.1 串口时钟使能,GPIO时钟使能; RCC_APB2PeriphClockCmd(); //USART1位于RCC_APB2PeriphClockCmd中// 15.2 串口复位; USART_DeInit(); //这一步不是必须的// 15.3 GPIO端口模式设置; GPIO_Init(); //TX模式设置为GPIO_Mode_AF_PP,RX模式设置为GPIO_Mode_IN_FLOATING // 15.4 串口参数初始化; USART_Init(); 15.5 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤); NVIC_Init(); USART_ITConfig(); 15.6 使能串口; USART_Cmd(); 15.7 编写中断处理函数; USARTx_IRQHandler(); 15.8 串口数据收发; void USART_SendData(); //发送数据到串口,DR// uint16_t USART_ReceiveData(); //接受数据,从DR读取接受到的数据// 15.9 串口传输状态获取; FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT); 16. 串口配置案例 //案例说明:设置PA9和PA10位USART1的TX和RX,开启USART_IT_RXNE接收中断,中断服务函数目的为,当USART_IT_RXNE发生,USART1接收数据并发送回去,需配合串口调试助手进行实验// #include "stm32f10x.h" //编写我的初始化函数// void My_USART1_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; //第一步,使能相关时钟// //使能GPIOA时钟,RCC_APB2PeriphClockCmd()位于stm32f10x.rcc.c文件中// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART1时钟// RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //第二步,串口复位// //将外设 USARTx 寄存器重设为缺省值,复位USART1,USART_DeInit()位于stm32f10x.usart.c文件中// USART_DeInit(USART1); //第三步,GPIO端口模式设置,PA9对应RXD,PA10对应TXD// //先对PA9进行设置,模式为复用推挽输出,引脚9,速度随意// GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出// GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; //引脚9// GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz; //随意设置// //根据上述GPIO_InitStruct中指定的参数初始化外设GPIOA寄存器,,GPIO_Init()位于stm32f10x.gpio.c文件中// GPIO_Init(GPIOA,&GPIO_InitStruct); //再对PA10进行设置,模式为浮空输入或带上拉输入,引脚10,速度随意// GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入// GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; //引脚9// GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz; //随意设置// //根据GPIO_InitStruct中指定的参数初始化外设GPIOA寄存器,GPIO_Init()位于stm32f10x.gpio.c文件中// GPIO_Init(GPIOA,&GPIO_InitStruct); //第四步,串口参数初始化,在电脑上进行串口通信时,串口调试软件也需按下述参数设置// USART_InitStruct.USART_BaudRate=115200; //波特率为115200// USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //不使用硬件流控制// USART_InitStruct.USART_Mode=USART_Mode_Rx | USART_Mode_Tx; //收发都使能,可用或运算// USART_InitStruct.USART_Parity=USART_Parity_No; //不用奇偶校验位// USART_InitStruct.USART_StopBits=USART_StopBits_1; //设置1个停止位// USART_InitStruct.USART_WordLength=USART_WordLength_8b; //设字长为8,因为不用奇偶校验// //根据上述USART_InitStruct中指定的参数初始化外设USART1寄存器,USART_Init()位于stm32f10x.usart.c文件中// USART_Init(USART1,&USART_InitStruct); //第五步,开启指定中断,并初始化NVIC// //NVIC初始化// NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn; //选择位于stm32f10x.h文件中STM32F10X_HD中的USART1_IRQn// NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能上述中断通道// NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; //因为没有别的中断,根据中断分组2,参数可设0~3之间// NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; //因为没有别的中断,根据中断分组2,参数可设0~3之间// //根据上述NVIC_InitStruct中指定的参数初始化外设NVIC寄存器,NVIC_Init()位于misc.c文件中// NVIC_Init(&NVIC_InitStruct); //使能USART1的USART_IT_RXNE中断,RXNE是状态寄存器USART_SR的第5位,意思是接收中断// USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //第六步,使能串口// //使能USART1外设,USART_Cmd()位于stm32f10x.usart.c文件中// USART_Cmd(USART1,ENABLE); } //第七步,编写中断服务函数// //函数名称USART1_IRQHandler是由位于启动文件startup_stm32f10x_hs.s文件里定义的// void USART1_IRQHandler(void) { u8 data; //第八步,串口状态获取// //检查USART1的接受中断USART_IT_RXNE发生与否,USART_GetITStatus()函数位于stm32f10x_usart.c文件中// if(USART_GetITStatus(USART1,USART_IT_RXNE)) { //第九步,串口数据收发,较为常用// //返回USART1最近接收到的数据,USART_ReceiveData()函数位于stm32f10x_usart.c文件中// data=USART_ReceiveData(USART1); //通过外设USART1发送单个数据,USART_SendData()函数位于stm32f10x_usart.c文件中// USART_SendData(USART1,data); } } //编写主函数// int main(void) { //设置优先级分组:先占优先级和从优先级// //设置分组2,即2位抢占优先级,2位响应优先级,NVIC_PriorityGroupConfig()位于misc.c文件中// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); My_USART1_Init(); while(1) { } } 17. usart.h代码讲解 #ifndef __USART_H #define __USART_H #include "stdio.h" #include "sys.h" #define USART_REC_LEN 200 //定义最大接收字节数 200// #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收// extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符// extern u16 USART_RX_STA; //接收状态标记// //如果想串口中断接收,请不要注释以下宏定义// void uart_init(u32 bound); //设置波特率// #endif 18. usart.c里中断服务函数USART1_IRQHandler函数代码讲解 void USART1_IRQHandler(void) //串口1中断服务程序// { u8 Res; //定义一个变量Res,用来接收数据// #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS// OSIntEnter(); #endif //*判断接收中断USART_IT_RXNE是否发生,发生则为1,不发生为*0// if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //RESET=0// { //*若接收中断USART_IT_RXNE发生,Res读取接收到的数据*// Res =USART_ReceiveData(USART1); //判断变量U16 USART_RX_STA的位15是否为0,当USART_RX_STA的位15为0时,则与运算后值为0,if返回1(真),反之if返回0(假)*// if((USART_RX_STA&0x8000)==0) { //*若USART_RX_STA的位15为0时,判断USART_RX_STA的位14是否为0*// if(USART_RX_STA&0x4000) { //*若USART_RX_STA的位14为1时,则判断Res接收的数据是否为0x0A,0x0A为换行标志*// if(Res!=0x0A) //*若Res接收的数据不是换行标志,则接收错误,重新开始*// USART_RX_STA=0; //*若Res接收的数据是换行标志,则USART_RX_STA的位15至1* // else USART_RX_STA|=0x8000; } //*若USART_RX_STA的位14为0时,执行else *// else { //*判断Res是否等于(接收到)0x0D,0x0D为回车标志*// if(Res==0x0d) //*若Res接收到回车标志,if为1(真),则USART_RX_STA位14至1 // USART_RX_STA|=0x4000; //*若Res未接收到回车标志,if为0(假),执行else// else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res; USART_RX_STA++; //*若USART_RX_STA值大于所设最大接收字节数,则接收数据错误,重新开始接收*// if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0; } } } } 上述代码中,变量U16 USART_RX_STA用法如下图所示: 19. main.c文件里主函数代码讲解 int main(void) { u16 t; u16 len; u16 times=0; delay_init(); //*延时函数初始化*// //设置NVIC中断分组2:2位抢占优先级,2位响应优先级// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart_init(115200); //串口初始化为115200// LED_Init(); //LED端口初始化// KEY_Init(); //初始化与按键连接的硬件接口// while(1) { //*判断USART_RX_STA的位15是否为1*// if(USART_RX_STA&0x8000) { //*若USART_RX_STA的位15为1*// len=USART_RX_STA&0x3fff; //得到此次接收到的数据长度// printf("rn您发送的消息为:rnrn"); for(t=0;t USART_SendData(USART1, USART_RX_BUF[t]); //向串口1发送第t个数据// //*等待发送结束,USART_FLAG_TC意思是Transmission Complete flag*// while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); } printf("rnrn"); //插入换行// USART_RX_STA=0; }else { times++; if(times%5000==0) //*times为5000的整数倍时*// { printf("rn战舰STM32开发板 串口实验rn"); printf("正点原子@ALIENTEKrnrn"); } if(times%200==0)printf("请输入数据,以回车键结束n"); //*times为200的整数倍时*// //*times为30的整数倍时,闪烁LED,提示系统正在运行*// if(times%30==0)LED0=!LED0; delay_ms(10); } } } 20. usart.c里中断服务函数printf()函数代码讲解 #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数// struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式// _sys_exit(int x) { x = x; } //重定义fputc函数// int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//循环发送,直到发送完毕// USART1->DR = (u8) ch; return ch; } #endif //若要对其他串口进行操作,只需将上述代码中的USART1改成USARTx即可。这段代码方便开发过程中查看代码执行情况以及一些变量值,该代码不需要修改,引入到 usart.h 即可// |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1609 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1540 浏览 1 评论
970 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
681 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1587 浏览 2 评论
1861浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
643浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
528浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
503浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-20 16:50 , Processed in 0.885677 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号