目录
1. RS232通讯
2. 实验程序
2.1 main.c
2.2 RS232.c
2.3 RS232.h
通过上一节的学习,已经基本了解了RS232的通讯过程,实际上,不管是RS485还是RS232都是基于串口的一种通讯方式!
STM32F4_RS485、RS232_light_2025的博客-CSDN博客
1. RS232通讯
RS232协议是1970年美国电子工业协会 EIA 联合贝尔系统、调制解调器厂家、计算机终端生产厂家共同制定的用于串行通信的标准(从上面介绍的UART的缺点来看,串口通信最致命的缺点就是没有统一的标准,导致不同器件之间的通讯变得异常的复杂,而 RS232 和 RS485 就是这样的一个标准,应用在串口之上,使得串口通信具有一定的标准)。
该标准规定采用一个标准的连接器,标准中对连接器的每个引脚的作用都加以规定,同时也对信号的电平加以规定。
接口:
该标准规定采用一个 25 引脚的 DB-25 连接器,标准中对连接器的每个引脚的信号内容加以规定。还对各种信号的电平加以规定;后来1BM的PC机将RS232简化成了 DB-9 连接器,再后来成了事实的标准(就像我们家用的三头插座一样,火线、零线、地线);现在工业控制的RS-232接口一般只使用RXD、TXD、GND三条线(STM32开发板中的原理图上也是如此)。
信号:
RS232标准规定逻辑 “1” 的电平为-5V到-15V,逻辑 “0” 的电平为+5V到+15V,选择该电气标准的目的在于提高抗干扰能力,增大通信距离,其传送的距离一般可达15m。
C1+:倍增器电荷泵电容器的正极。
V+:充电泵产生的+5.5V。
C1-:倍增器电荷泵电容器的负极。
C2+:反转电荷泵电容器的正极。
C2-:反转电荷泵电容器的负极。
V-:-5.5V由电荷泵产生。
DOUT2:RS-232驱动输出。
RIN2:RS-232接收输入。
VCC:+3V~+5.5V供给电圧。
GND:地。
DOUT1:RS-232驱动输出。
RIN1:RS-232接收输入。
ROUT1:RS-232接收输出。
DIN1:RS-232驱动输入。
DIN2:RS-232驱动输入。
ROUT2:RS-232接收输出。
RS232存在的问题:
1. 接口的信号电平较高(-15V~+15V),易损坏接口电路芯片,又因为与TTL电平不兼容,所以需要使用电平转换芯片才能与TTL电路连接。
2. 通信速度较低,不适合用于那些高速通信的场合。
3. 易产生共模干扰,抗噪声干扰性弱。
4. 传输距离较短,一般情况只有15m。
最后强调一点:程序编程方面 RS232 和 串口 没有任何区别,只是在硬件方面做出了一些改善。(所以说 RS232 本质上还是通过串口在收发数据,简单点来说,不过是把接线接口的电气特性更换了)
2. 实验程序
实验准备:
本实验最终实现STM32F407开发板和电脑通过RS232进行通讯,所以需要 USB转RS232 串口线; USB 端接电脑USB接口,DB-9 接口接自己的开发板,至于是公头还是母头,根据自己的开发板选择即可;
STM32F407开发板还需要将P9插针中的COM2_RX和TX接,COM2_TX和RX接;PA2,PA3引脚为串口 2 的收发引脚;
实验现象:
本实验的实验现象为:程序烧录后,通过串口助手可以发送命令控制开发板LED0、LED1 以及蜂鸣器;同样开发板上也可以通过按键发送信息给串口,实现 STM32F4 通过 RS232 和电脑进行简单通讯;
2.1 main.c
#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "Key.h"
#include "RS232.h"
#include "beep.h"
//函数声明
void LED_BEEP_Control(void);
void Key_InterruptInit(void);
void EXTI4_IRQHandler(void);
void EXTI2_IRQHandler(void);
void USART2_IRQHandler(void);
int Control_Flag=0; //设置一个状态位
unsigned int i;
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168);
uart_init(115200); //切记:不初始化延迟函数和串口是不能用LCD的
LED_Init();
LCD_Init();
BEEP_Init();
RS232_Init(9600); //初始化RS232,设置波特率为9600
Key_InterruptInit();
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"RS232 TEXT");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2023/06/08");
LCD_ShowString(30,140,200,16,16,"Input 0,LED0 Light");
LCD_ShowString(30,160,200,16,16,"Input 1,LED1 Light");
LCD_ShowString(30,180,200,16,16,"Input 2,Turn on the buzzer");
LCD_ShowString(30,200,200,16,16,"Input 3,Turn off the buzzer");
RS232_SendString(USART2,"请输入您的指令:\r\n");
RS232_SendString(USART2," 输入0: LED0点亮\r\n");
RS232_SendString(USART2," 输入1: LED1点亮\r\n");
RS232_SendString(USART2," 输入2: 打开蜂鸣器\r\n");
RS232_SendString(USART2," 输入3: 关闭蜂鸣器\r\n");
while(1)
{
LED_BEEP_Control();
}
}
void LED_BEEP_Control(void)
{
switch(Control_Flag)
{
case 1:
LED0=0;
LED1=1;
delay_ms(10);
LCD_ShowString(30,230,200,16,16,"LED0 Light");
//RS232_SendString(USART2,"LED0已点亮\r\n\r\n"); 打开此功能可以看到,按下按键后串口显示的现象
break;
case 2:
LED0=1;
LED1=0;
delay_ms(10);
LCD_ShowString(30,230,200,16,16,"LED1 Light");
//RS232_SendString(USART2,"LED1已点亮\r\n\r\n");
break;
case 3:
LED0=!LED0;
delay_ms(20);
LED1=1;
delay_ms(20);
GPIO_SetBits(GPIOF,GPIO_Pin_8);
delay_ms(20);
LCD_ShowString(30,230,200,16,16,"Turn on the buzzer");
//RS232_SendString(USART2,"蜂鸣器已打开\r\n\r\n");
break;
case 4:
LED1=!LED1;
delay_ms(20);
LED0=1;
delay_ms(20);
GPIO_ResetBits(GPIOF,GPIO_Pin_8);
delay_ms(20);
LCD_ShowString(30,230,200,16,16,"Turn off the buzzer");
//RS232_SendString(USART2,"蜂鸣器已关闭\r\n\r\n");
break;
}
}
void USART2_IRQHandler(void)
{
uint8_t temp;
if(USART_GetFlagStatus(USART2,USART_IT_RXNE)!=0)
{
temp=USART_ReceiveData(USART2); //通过电脑串口助手发命令给temp,根据temp的不同数值设置相关状态位
//USART_SendData(USART2,temp);
switch(temp)
{
case'0':
Control_Flag=1;
RS232_SendString(USART2,"LED0已点亮\r\n\r\n");
break;
case'1':
Control_Flag=2;
RS232_SendString(USART2,"LED1已点亮\r\n\r\n");
break;
case'2':
Control_Flag=3;
RS232_SendString(USART2,"蜂鸣器已打开\r\n\r\n");
break;
case'3':
Control_Flag=4;
RS232_SendString(USART2,"蜂鸣器已关闭\r\n\r\n");
break;
}
}
}
void Key_InterruptInit(void)
{
KEY_Init(); //按键对应的IO初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE); //想要使用按键控制外部中断,必须使能SYSCFG时钟
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2); //PE2连接中断线2,映射按键KEY2
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4); //PE4连接中断线4,映射按键KEY0
EXTI_ClearITPendingBit(EXTI_Line2);
EXTI_ClearITPendingBit(EXTI_Line4);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line2 | EXTI_Line4; //KEY0 和 KEY2
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //KEY0 和 KEY2 按下,对应引脚输入低电平
EXTI_Init(&EXTI_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x03;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI2_IRQHandler(void) //对应于KEY2
{
delay_ms(10); //按键消抖
if(KEY2==0)//KEY2按下
{
Control_Flag++; //按键控制状态位改变
if(Control_Flag>4)
Control_Flag=1;
}
EXTI_ClearITPendingBit(EXTI_Line2);//消除中断线2上的中断标志位
}
void EXTI4_IRQHandler(void) //对应于KEY0
{
delay_ms(10);//按键消抖
if(KEY0==0)//KEY0按下
{
Control_Flag--;
if(Control_Flag<1)
Control_Flag=4;
}
EXTI_ClearITPendingBit(EXTI_Line4);//消除中断线4上的中断标志位
}
2.2 RS232.c
#include "stm32f4xx.h"
#include "RS232.h"
#include "delay.h"
//初始化RS232
//初始化IO口 和 串口2
//根据STM32F407开发板P9插针,只需要将跳线帽的PA2和COM2_RX接,PA3和COM2_TX接即可;
//bound:波特率
void RS232_Init(u32 bound)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //使能USART2时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为串口2
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为串口2
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //设置为推挽输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure);
//串口2初始化
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=bound; //设置波特率
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; //1个停止位
USART_InitStructure.USART_WordLength=USART_WordLength_8b; //字长为8位
USART_Init(USART2,&USART_InitStructure);
USART_Cmd(USART2,ENABLE); //使能串口2
USART_ClearFlag(USART2,USART_FLAG_TC); //清除串口2中断标志位
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //串口中断命令,USART_IT_RXNE是串口状态寄存器的接收缓存区的标志位,该函数表示开启接收中断
//串口2中断优先级配置
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; //子优先级3
NVIC_Init(&NVIC_InitStructure);
}
//RS232发送字符
unsigned char RS232_SendChar(USART_TypeDef* USARTx,unsigned char ucChar)
{
while(!USART_GetFlagStatus(USARTx,USART_FLAG_TXE));
USART_SendData(USARTx,ucChar);
return ucChar;
}
//RS232发送字符串
void RS232_SendString(USART_TypeDef* USARTx,unsigned char* pucStr)
{
while(*pucStr!='\0')
{
RS232_SendChar(USARTx,*pucStr++);
}
}
//接收缓存区标志位置1下的非阻塞接收字符
unsigned char RS232_ReceiveChar_NonBlocking(USART_TypeDef* USARTx)
{
if(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE))
{
return USART_ReceiveData(USARTx);
}
else
return 0;
}
2.3 RS232.h
#ifndef _RS232__H_
#define _RS232__H_
void RS232_Init(u32 bound);
unsigned char RS232_SendChar(USART_TypeDef* USARTx,unsigned char ucChar);
void RS232_SendString(USART_TypeDef* USARTx,unsigned char* pucStr);
unsigned char RS232_ReceiveChar_NonBlocking(USART_TypeDef* USARTx);
#endif