STM32F4_通过RS232实现和PC端通讯

目录

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 接口接自己的开发板,至于是公头还是母头,根据自己的开发板选择即可;

STM32F4_通过RS232实现和PC端通讯_第1张图片

        STM32F407开发板还需要将P9插针中的COM2_RX和TX接,COM2_TX和RX接;PA2,PA3引脚为串口 2 的收发引脚;

STM32F4_通过RS232实现和PC端通讯_第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
 

STM32F4_通过RS232实现和PC端通讯_第3张图片

 

你可能感兴趣的:(STM32,stm32,单片机,嵌入式硬件)