串口通信实验
来源:互联网 发布:算法描述的发展现状 编辑:程序博客网 时间:2024/06/06 18:02
前置技能
串行通信基本原理
USART串口通信配置
一,串口操作相关库函数:
获取状态标志位函数-操作USART_SR寄存器
// 获取状态标志位FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);// 清除状态标志位void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);// 获取中断状态标志位ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);// 清除中断状态标志位void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
接收发送数据函数-操作USART_DR寄存器
// 发送数据到串口(通过写USART_DR寄存器发送数据)void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);// 接收数据(从USART_DR寄存器读取接收到的数据)uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
串口配置函数
// 串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);// 使能串口void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);// 使能相关中断void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
二,串口配置的步骤
1,串口时钟使能,GPIO时钟使能 RCC_APB2PeriphClockCmd()2,串口复位 USART_DeInit();3,GPIO端口模式设置 GPIO_Init();4,串口参数初始化 USART_Init()5,开启中断并初始化NVIC NVIC_Init(); USART_ITConfig();6,使能串口 USART_Cmd();7,中断函数逻辑 USARTx_IRQHandler();8,串口数据发送 void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); uint16_t USART_ReceiveData(USART_TypeDef* USARTx);9,串口传输状态获取 ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
三,串口引脚配置
USART1_TX : 复用推挽输出 USART1_RX : 浮空输入
四,设计串口通信协议
数据以(0x0D),(0x0A)结尾(回车,换行符)时,认为数据接收完成 如:ABCDEFGHIJK…..(0x0D),(0x0A)
五,代码实现
SYSTEM/usart/usart.h头文件
#ifndef __USART_H#define __USART_H#include "stdio.h"#include "sys.h"#define USART_REC_LEN 200 // 最大接收字节数 200#define EN_USART1_RX 1extern u8 USART_RX_BUF[USART_REC_LEN]; // 串口接收数据缓冲数组-200字节// 16位接收状态标记:// 0-13位接收有效数据数量 // 14位:接收到0x0D标志 // 15位:接收完成标志extern u16 USART_RX_STA;//设置串口波特率void uart_init(u32 bound);#endif
SYSTEM/usart/usart.c
u8 USART_RX_BUF[USART_REC_LEN]; // 串口接收数据缓冲数组 200字节// 16位接收状态标记:// 0-13位接收有效数据数量 // 14位:接收到0x0D标志 // 15位:接收完成标志u16 USART_RX_STA=0;void uart_init(u32 bound){ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 初始化GPIOA,USART1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX GPIOA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //Usart1 NVIC 中断优先级配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 串口1 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; // 抢占3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 响应1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能-开启 NVIC_Init(&NVIC_InitStructure); //USART配置 USART_InitStructure.USART_BaudRate = bound; // 设置波特率-外部传参 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长 8|9 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(USART1, &USART_InitStructure); // 初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收中断 USART_Cmd(USART1, ENABLE); // 使能串口1}void USART1_IRQHandler(void){ u8 Res; //判断是否是接收中断 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ // 读取接收到的数据 Res =USART_ReceiveData(USART1); // 读取USART_RX_STA-bit15判断是否上一次已经接收完成了,还没有清标志位(外部主函数还没读走) if((USART_RX_STA&0x8000)==0){ // 读取USART_RX_STA-bit14 if(USART_RX_STA&0x4000){ // 已接收到0x0D //本次不是0x0A-错误数据,置位USART_RX_STA重新读取 if(Res!=0x0a)USART_RX_STA=0; else USART_RX_STA|=0x8000; //本次是0x0A,置位USART_RX_STA-Bit15=1 } else { // 如果上一次没有接收到0x0D //本次是0x0D,置位USART_RX_STA-Bit14=1 if(Res==0x0d){ USART_RX_STA|=0x4000; }else{//本次不是0x0D,存入字节数组,更新数量 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; } } } } }}
USER/main.c 主函数
#include "led.h"#include "delay.h"#include "key.h"#include "sys.h"#include "usart.h" int main(void) { u16 t; // 循环计数器 u16 len; // 接收到的数据长度 u16 times=0; // 每10ms+1 delay_init(); // 延迟函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2,2位抢占2位响应 uart_init(115200); // 设置串口1波特率为115200 LED_Init(); // LED端口初始化 KEY_Init(); // 按键端口初始化 // 主循环读取串口数据 while(1) { if(USART_RX_STA&0x8000) // 接收数据完成 { len=USART_RX_STA&0x3fff; // 读取数据长短 printf("\r\n您发送的消息为:\r\n\r\n"); for(t=0;t<len;t++) // 循环发送数据 { USART_SendData(USART1, USART_RX_BUF[t]); // 向串口1发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);// 等待发送完成 } printf("\r\n\r\n"); // 换行 USART_RX_STA=0; // 置位USART_RX_STA,串口下一次接收使用 }else // 接收数据未完成或无数据时 { times++; if(times%5000==0) // 每50秒 { printf("\r\n串口实验\r\n"); } if(times%200==0)printf("2m无数据\n"); // 每2秒 if(times%30==0)LED0=!LED0; // 每300msLED亮灭切换 delay_ms(10); // 延时10ms } } }
以上代码实现: 电脑通过串口助手发送数据给单片机 单片机接收数据进入接收数据串口中断 根据通信协议处理数据,保存数据到字节数组 将接收到的数据回写给串口,并打印输出
0 0
- 单片机串口通信实验
- 串口通信实验
- 串口通信实验
- 串口通信--网络实验2
- 基于C8051F410的串口通信实验
- 实验二 串口与节点通信(上)
- STC 51 单片机 串口通信实验
- 1-4 实验3 串口通信
- 1-5 实验4 串口通信2
- 上位机与arm串口通信实验
- s5pv210裸机实验之串口通信
- 节点-PC串口通信实验问题
- CC2530基础实验四 串口通信
- 170806 通信-ZigBee协议栈串口实验
- 基于FPGA Uart串口通信实验
- Exynos4412异步串口通信及实验
- ARM课程实验二 UART 串口通信实验
- S3C2410 实验五—— 串口通信实验
- CRC(Class Responsibility Collaborator) 模型简介
- Linux运维学习八大禁忌
- 修改 Java 中的接口有什么作用?
- Apple如何知道你用私有API?
- android:configChanges含义及其用法
- 串口通信实验
- java 一点内容(4)
- 创建AndroidStudio工程
- 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验
- 运维的85条规则
- dpkg: error: unknown option --add-architecture
- 《算法导论》读书笔记(三)
- 解决windows 远程桌面链接的问题 3389端口不能访问
- 查看mysql实际执行语句(被mysql优化后执行的sql)