串口作为 C 语言嵌入式中的重要的通信方式, 一直是面试官考察 C 语言软件工程师能力重要标志小编我当时就被问懵逼了
串口
串口通信是指串行通信, 它的优点是使用的资源少(占用的引脚少), 它的缺点是传输速度慢(每次传输一个 bit 位);
小编推荐一个学 C 语言 / C++ 的学习裙 六九九, 四七零, 五九六 , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
串口通信
从上图可以看到串口通信是由两根线控制的, 一根是 TX(以主机为视角)也就是发送线, 还有一根 RX 也就是接收线; 发送的数据通过发送线发送给从机, 接收的数据通过接收线从从机处接收, 所以发送和接收是分开的, 相互之间不影响所以串口 RS232 可以实现全双工通信, 全双工通信就是在同一时间进行发送和接收数据但是串口 RS232 在工程中使用的很少, 因为它的传输距离很短, 不适合在工程中使用; 所以就有了串口 RS485, 它可以实现长距离的数据传输, 但是它是半双工通信, 所谓的半双工通信就是同一时间只能发送数据或者只能接收数据, 这就是他们的不同点, 面试官常常会问到这个, 其他的使用起来都一样给大家总结一下:
串口 RS232: 传输距离短, 全双工通信;
串口 RS485: 传输距离唱, 半双工通信, 通过一个控制端, 控制当前处于发送还是接收状态;
所以今天给大家重点讲解串口 RS485, 其实和大家讲, 串口使用特别特别简单, 只要将串口初始化 OK 了, 接下来只要把数据赋值到发送寄存器中就可以了, 怎么传送数据是串口自己做的事情, 还有接收数据, 你只要从接收寄存器中将数据读取出来就可以了, 超级简单, 就像你打电话, 你只要把电话号码拨通, 接下来用嘴说话, 用耳朵去听就好了, 没人要求你掌握你说的话到底是怎样传输的要知道我们的任务是使用好这些功能而不是去创造这些功能, 每一层的工程师做好自己的工作就 OK 了, 至于电话那不是有人给你做出来了吗? 你只要会用就可以了
好了接下来就和大家去了解如何初始化串口还是那句话, 初始化什么设备就先创建那个设备的结构体, 但是上面和大家说了, 串口通信需要使用两个引脚, 所以我们要先初始化对应的引脚, 之后再初始化串口设备
初始化引脚: 很简单就不和大家多说了
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能 GPIOA 时钟
- // 串口 1 对应引脚复用映射(引脚要配置为串口功能, 和大家讲过引脚对应很多功能使用前要先选择好)
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); //GPIOA9 复用为 USART1
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //GPIOA10 复用为 USART1
- //USART1 端口配置
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9 与 GPIOA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用功能
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 速度 50MHz
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽复用输出
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
- GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化 PA9,PA10
配置串口:
- USART_InitTypeDef USART_InitStructure; // 创建设备结构体
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能 USART1 时钟
- USART_InitStructure.USART_BaudRate = bound; // 波特率设置, 每秒传输多少个 bit 位
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为 8 位数据格式, 每次传输的数据为 1 个字节
- 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); // 初始化串口 1
- USART_Cmd(USART1, ENABLE); // 使能串口 1 , 串口初始化结束之后就要开启串口功能
另外一般接收数据我们采用中断方式, 有数据过来了, 数据放在接收缓冲区中, 我们通过中断将数据读取出来, 避免数据被下一个数据覆盖造成丢失数据的情况所以要配置中断和中断触发函数
配置中断:
- NVIC_InitTypeDef NVIC_InitStructure; // 创建中断结构体
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 开启相关中断
- //Usart1 NVIC 配置
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;// 串口 1 中断通道
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;// 抢占优先级 3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;// 子优先级 3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ 通道使能
- NVIC_Init(&NVIC_InitStructure);// 根据指定的参数初始化 VIC 寄存器
发送数据函数:
- #define Int08U unsigned char
- void UART1PutChar(Int08U ch)
- {
- (RS485 这需要使能发送, 因为 RS485 是单双工, 默认状态是接收状态, 所以这里需要改变控制发送和接收状态的端口的电平例如: 将引脚 PF8 置为低电平, RS232 则不需要这一步)
- while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));// 判断前一个数据是否发送完成, 若未完成在等待完成
- USART_SendData(USART1,ch); // 发送数据的函数, 只要将数据放到这里就 OK 了
- (RS485 数据发送结束后还要将状态改为接收状态, 例如: 将引脚 PF8 置为高电平, RS232 则不需要这一步)
- }
小编推荐一个学 C 语言 / C++ 的学习裙 六九九, 四七零, 五九六 , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
接收函数:
- Int08U UART1GetChar(void)
- {
- return USART_ReceiveData(USART1);// 返回接收寄存器中的数据就 OK 啦
- }
中断函数:
- void USART1_IRQHandler(void) // 这个函数的名称是固定的, 用的串口几就是 USART 几, 上面发送和接收函数名自己定义
- {
- Int08U rev;
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)// 判断中断标志位如果寄存器中有数据
- {
- rev = UART1GetChar();
- UART1PutChar(Rev);
- USART_ClearITPendingBit(USART1, USART_IT_RXNE);// 处理结束之后清除中断标志位
- }
- }
这个函数就是是想将接受到的数据再发送出来
看完上面的我们梳理一下使用串口的步骤:
1 配置管脚为串口输入输出模式
2 配置串口参数如: 波特率字长停止位校验位数据控制流和收发模式, 之后初始化并开始串口功能
3 配置中断
4 封装发送和接收函数
5 封装中断函数
就上面 5 个步骤, 简明扼要, 只要配置好, 你就可以实现通信了还是那句话学习 C 语言和嵌入式并不难, 我们只要将结构捋一捋, 条理很很明白, 写程序之前一定要先思考, 将步骤全都写出来
你要实现什么功能?
这些功能都需要哪些设备?
这些设备该如何使用和配置?
从大到小, 从外到内, 从总功能到细节功能! 只有这样一步一步, 你就会发现使用 C 语言实现嵌入式功能很简单, 都是模块化的事情, 你要做的就是思考思考再思考
好了谢谢大家今天的陪伴, 如果大家喜欢话点个赞或评论两句吧, 小编需要大家的支持当然如果小编哪里写错了还希望大家批评指正, 再次谢谢大家了
小编推荐一个学 C 语言 / C++ 的学习裙 六九九, 四七零, 五九六 , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
这些是 C/C++ 能做的
来源: http://www.jianshu.com/p/0962c1bff158