STM32入门笔记10 |
您所在的位置:网站首页 › STM32串口USART控制继电器 › STM32入门笔记10 |
USART串口通信
通信接口
通信的目的: 将一个设备的数据传送到另一个设备, 扩展硬件系统通信协议: 制定通信的规则, 通信双方按照协议规则进行数据收发
名称引脚双工时钟电平设备USARTTX、RX全双工异步单端点对点I2CSCL、SDA半双工同步单端多设备SPISCLK、MOSI、MISO、CS全双工同步单端多设备CANCAN_H、CAN_L半双工异步差分多设备USBDP、DM半双工异步差分点对点
USART有同步和异步两种通讯方式, 但同步只用作特殊功能, 一般只使用异步通讯 串口通信 串口是一种应用十分广泛的通讯接口, 串口成本低, 容易使用、通信线路简单, 可实现两个设备的互相通信单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信, 极大地扩展了单片机的应用范围, 增强了单片机系统的硬件实力 通信方式 串行通信与并行通信 串行通信: 数据字节一位位地依次传送的通信方式, 串行通信的速度慢, 但用的传输线条数少, 成本低,适用于远距离的数据传送并行通信: 数据字节的各位同事传送的通信方式, 优点是数据传送速度快, 缺点是占用的传输线条数多, 适用于近距离通信, 远距离通信的成本较高 串行异步通信和串行同步通信 异步通信:一次通信传送一个字符帧, 发送的字符之间的时间间隔可以是任意的, 优点是通信设备简单、价格低廉, 但因为具有起始位和停止位, 传输效率较低 同步通信:进行通信前先建立同步, 发送频率和接受方的接受频率要同步。在发送信息时, 将多个字符加上同步字符组成一个信息帧, 有一个统一的时钟控制发送端的发送, 接收端识别到同步字符后, 就认为开始一个信息帧, 此后位数作为实际传输信息处理。优点: 传输速度较快, 可用于点对多点 缺点: 需要使用专用的时钟控制线实现同步, 对于长距离通信成本较高, 通信速率也会降低。一般用于同一PCB上芯片级之间的通信 串口参数及时序(串行异步通信) 波特率: 串口通信的速率起始位: 标志一个数据帧的开始, 固定为低电平数据位: 数据帧的有效载荷, 1为高电平, 0为低电平, 低位先行校验位: 用于数据验证, 根据数据位计算得来停止位: 用于数据帧间隔, 固定为高电平差分信号的干扰小, 一般TTL电平和RS232电平传输距离只有十几米, 而RS485电平的传输范围可达数千米 串口时序![]() 按键输入端为PA1 采用EXTI中断 PA0输出控制LED1, PA2输出控制LED2 LED2可通过按键控制 LED1通过上位机下达指令控制 利用Timer定时器每隔十秒进入一次中断, 获取LED1和LED2的亮灭状态 硬件接线PA0接LED1, PA1接按键,PA2接LED2,PA9为单片机的Tx发送端接CH3400的Rx端,PA10为单片机的Rx接收断接CH3400的Tx端 初始化USART /* 串口通信初始化函数 抢占优先级0 响应优先级0 */ void Serial_Init(void) { // RCC使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置GPIO // TX 发送端 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // RX 接收断 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置USART串口通信 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate=9600; // 波特率 USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; // 无流控 USART_InitStructure.USART_Mode=USART_Mode_Rx | USART_Mode_Tx; // 两种模式都打开 USART_InitStructure.USART_Parity=USART_Parity_No; // 奇偶校验 USART_InitStructure.USART_StopBits=USART_StopBits_1; // 停止位 USART_InitStructure.USART_WordLength=USART_WordLength_8b; // 8位 USART_Init(USART1, &USART_InitStructure); // 打开USART中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 接收寄存器非空(正在接收) // 配置NVIC NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_Init(&NVIC_InitStructure); // 启动USART USART_Cmd(USART1, ENABLE); } 主要代码 Serial.c #include "stm32f10x.h" char Down_String[] = "AABBCCDD01000000\r\n"; // 保存从下位机获取的数据 char Header[] = "AABBCCDD00"; // 协议头+数据来源 char Up_String[100]; // 保存从上位机传送来的数据 uint8_t idx; //下标 uint8_t Decode_Flag; /* 串口通信初始化函数 抢占优先级0 响应优先级0 */ void Serial_Init(void) { // RCC使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置GPIO // TX 发送端 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // RX 接收断 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置USART串口通信 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate=9600; // 波特率 USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; // 无流控 USART_InitStructure.USART_Mode=USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_Parity=USART_Parity_No; // 奇偶校验 USART_InitStructure.USART_StopBits=USART_StopBits_1; // 停止位 USART_InitStructure.USART_WordLength=USART_WordLength_8b; // 8位 USART_Init(USART1, &USART_InitStructure); // 打开USART中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 接收寄存器非空(正在接收) // 配置NVIC NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_Init(&NVIC_InitStructure); // 启动USART USART_Cmd(USART1, ENABLE); } /* 发送单个数据 */ void Send_Byte(uint16_t Byte) { USART_SendData(USART1, Byte); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完毕 } /* 发送字符串 */ void Serial_SendString(char * String) { uint8_t i; for(i=0; String[i] != '\0'; ++i) { Send_Byte(String[i]); } } /* 向上位机传送监控的信息 */ void Transimit_Message(void) { Serial_SendString((char*)Down_String); } /* 获取LED信息 LED为低电平驱动 */ void Get_LEDInfo(void) { // LED1 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1){ // LED1灭 Down_String[11] = '0'; }else{ Down_String[11] = '1'; } // LED2 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)==1){ // LED2灭 Down_String[13] = '0'; }else{ Down_String[13] = '1'; } } /* 下位机解码上位机传送的信息 */ uint8_t Decode_Info(char * String) { for(uint8_t i=0; i < 8; ++i) { if(String[i] != Header[i]) { return 0; } } // 判断是否有保留位 for(uint8_t i=12; i // 判断标志位 if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET) { // 获取LED信息 Get_LEDInfo(); // 将信息发送给上位机 Transimit_Message(); // 清除标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } main.c #include "stm32f10x.h" #include "delay.h" #include "LED.h" #include "key.h" #include "Timer.h" // 定时器 10s 获取一次信息 #include "Serial.h" // 串口相关程序 // 上位机控制LED亮灭 int main(void) { LED1_Init(); LED2_Init(); Key_Init(); Timer_Init(); Serial_Init(); while(1) { // 接收到一个完整协议的数据 进行解析 if(idx >= 16) { // 解码 Decode_Flag = Decode_Info((char*)Up_String); // 打印解码信息 Decode_Info_Print(); idx = 0; } } } 效果展示
【单片机作业: USART通信案例上位机控制LED灯亮灭】 参考资料嵌入式单片机STM32原理及应用 【STM32入门教程-2023持续更新中】 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |