25.1.3 UART串口通信

发布于:2025-02-11 ⋅ 阅读:(80) ⋅ 点赞:(0)

1.FSMP1A开发板进行串口通信实验:

功能:电脑输入LED_ON点亮扩展版LED灯,输入LED_OFF熄灭扩展版LED灯

代码实现:

uart4.c

#include "uart4.h"
//串口初始化
void uart4_init(){
    //使能UART4外设时钟
    RCC->MP_APB1ENSETR |=(0X1<<16);
    //使能GPIOB/GPIOG外设时钟
    RCC->MP_AHB4ENSETR |=(0X1<<1);
    RCC->MP_AHB4ENSETR |=(0X1<<6);
    //设置PB2/PG11复用为UART4功能
    //PB2
    GPIOB->MODER &=(~(0X3<<4));//先清零
    GPIOB->MODER |=(0X2<<4);//设置成复用模式
    GPIOB->AFRL &=(~(0XF<<8));//先清零
    GPIOB->AFRL |=(0X8<<8);//设置成UART4-RX模式
    //PG11
    GPIOG->MODER &=(~(0X3<<22));//先清零
    GPIOG->MODER |=(0X2<<22);//设置成复用模式
    GPIOG->AFRH &=(~(0xF<<12));//先清零
    GPIOG->AFRH |=(0X6<<12);//设置成UART4-TX模式

    //禁用串口UE=0,因为其他相关设置是在UE=0情况下设置的
    USART4->CR1 &=(~(0X1<<0));
    //设置8bit数据位
    USART4->CR1 &=(~(0X1<<12));
    USART4->CR1 &=(~(0X1<<28));
    //设置没有校验位
    USART4->CR1 &=(~(0X1<<10));
    //设置不分频
    USART4->PRESC &=(~(0XF<<0));
    //设置16倍过采样
    USART4->CR1 &=(~(0X1<<15));
    //设置1bit停止位
    USART4->CR2 &=(~(0X3<<12));
    //设置115200波特率
    USART4->BRR=0X22B;
    //使能发送器
    USART4->CR1 |=(0X1<<3);
    //使能接收器
    USART4->CR1 |=(0X1<<2);
    //使能串口
    USART4->CR1 |=0X1;
}

//封装单个字符发送函数
void putchar(char ch){
    //判断发送数据寄存器是否为空,不为空则等待
    while(!(USART4->ISR&(0X1<<7)));
    //为空,向发送数据寄存器写入数据
    USART4->TDR=ch;
    //等待发送完成
    while(!(USART4->ISR&(0x1<<6)));
}

//单个字符的接收
char getchar(){
    //判断接收数据寄存器是否有数据
    //没有数据则等待
    while(!(USART4->ISR&(0X1<<5)));
    //有数据就将数据读取返回放置内存中变量
    return USART4->RDR;
}

//封装字符串的输入
void gets(char *s)
{
    //循环调用单个字符接收

    //等待读取到回车键\r,字符串接收
    while(1){
        *s=getchar();
        if((*s)=='\r'){
            break;
        }
        putchar(*s);//让输入的字符串回显到电脑串口工具
        s++;
    }
    *s='\0';
    putchar('\n');
    putchar('\r');
}

//字符串输出
void puts(char *s)
{

    //循环调用单个字符的发送
    //直到遇到\0结束
    while(*s){
        putchar(*s);
        s++;
    }
    putchar('\0');
    //最后末尾发送一个换行一个回车
    putchar('\n');
    putchar('\r');
}

//自定义strcmp函数
int my_strcmp(const char *des,const char *src){
    while(*des==*src){
        if(*des=='\0'||*src=='\0'){
            break;
        }
        des++;
        src++;
    }
    return *des-*src;
}

uart.h

#ifndef __UART4__H__
#define __UART4_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_uart.h"
void uart4_init();
void putchar(char ch);
char getchar();
void gets(char *s);
void puts(char *s);
int my_strcmp(const char *des,const char *src);


#endif

led.c

#include "led.h"
//初始化LED1-3所对应的GPIO引脚以及使能
void led_init(){
    //GPIO初始化
    //将RCC_MP_AHB4ENSETR寄存器第[5:4]位设置为1,使能GPIOE和F外设时钟
    RCC->MP_AHB4ENSETR |=(0X3<<4);
    //1.GPIOE_MODER[21:20]设置为01,PE10管教为输出模式
    GPIOE->MODER &=(~(0x3<<20));//先清零
    GPIOE->MODER |=(0x1<<20); //再置位
     //1.GPIOF_MODER[21:20]设置为01,PF10管教为输出模式
    GPIOF->MODER &=(~(0x3<<20));//先清零
    GPIOF->MODER |=(0x1<<20); //再置位
     //1.GPIOE_MODER[17:16]设置为01,PE8管教为输出模式
    GPIOE->MODER &=(~(0x3<<16));//先清零
    GPIOE->MODER |=(0x1<<16); //再置位

    //2.GPIOE_OTYPER[10]设置为0,PE10管脚推挽输出
    GPIOE->OTYPER &=(~(0x1<<10));//先清零
   //2.GPIOF_OTYPER[10]设置为0,PF10管脚推挽输出
    GPIOF->OTYPER &=(~(0x1<<10));//先清零
    //2.GPIOE_OTYPER[8]设置为0,PE8管脚推挽输出
    GPIOE->OTYPER &=(~(0x1<<8));//先清零

    //3.GPIOE_OSPEEDR[21:20]设置为00,PE10管脚为低速输出
    GPIOE->OSPEEDR &=(~(0x3<<20));//先清零
    //3.GPIOF_OSPEEDR[21:20]设置为00,PF10管脚为低速输出
    GPIOF->OSPEEDR &=(~(0x3<<20));//先清零
    //3.GPIOE_OSPEEDR[17:16]设置为00,PE8管脚为低速输出
    GPIOE->OSPEEDR &=(~(0x3<<16));//先清零

    //4.GPIOE_PUPDR[21:20]设置为00,PE10管脚无上拉下拉电阻
    GPIOE->PUPDR &=(~(0x3<<20));//先清零
    //4.GPIOF_PUPDR[21:20]设置为00,PF10管脚无上拉下拉电阻
    GPIOF->PUPDR &=(~(0x3<<20));//先清零
    //4.GPIOE_PUPDR[17:16]设置为00,PE8管脚无上拉下拉电阻
    GPIOE->PUPDR &=(~(0x3<<16));//先清零

}
//对引脚和哪盏灯控制,参数1:确定哪盏灯,参数2:确定开灯为1,关灯为0
void led_ctl(int which,int cmd){
    switch(which){
        case 1:
            if(cmd==0)//关灯
                GPIOE->ODR &=(~(0x1<<10));
            else if(cmd==1)//开灯
                GPIOE->ODR |=(0x1<<10); 
            break;
        case 2:
        if(cmd==0)//关灯
            GPIOF->ODR &=(~(0x1<<10));
        else if(cmd==1)//开灯
            GPIOF->ODR |=(0x1<<10); 
        break;
        case 3:
        if(cmd==0)//关灯
            GPIOE->ODR &=(~(0x1<<8));
        else if(cmd==1)//开灯
            GPIOE->ODR |=(0x1<<8); 
        break;
    }
}

led.h

#ifndef __LED__
#define __LED__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_uart.h"
/* typedef struct{ */
/*     unsigned int MODER; */
/*     unsigned int OTYPER; */
/*     unsigned int OSPEEDR; */
/*     unsigned int PUPDR; */
/*     unsigned int IDR; */
/*     unsigned int ODR; */
/*     unsigned int BSRR; */
/* }gpio_t; */
/*  */
/* #define GPIOE (*(gpio_t*)0x50006000) */
/* #define GPIOF (*(gpio_t*)0x50007000) */
/* #define RCC (*(unsigned int*)0x50000A28) */

    void led_init();
    void led_ctl(int which,int cmd);

#endif

main.c

#include "uart4.h"
#include "led.h"

int main()
{
	uart4_init();//uart4串口初始化
	led_init();//led1-3初始化
	/* char ch; */
	/* //电脑端发送数据,接收数据 */
	/* while(1){ */
	/* 	//读取电脑发送的字符 */
	/* 	ch=getchar(); */
	/* 	//将字符+1后返回给电脑 */
	/* 	putchar(ch+1); */
	/* 	putchar('\n');//换行 */
	/* 	putchar('\r');//回车 */
	/* 	 */
	/* } */
	char buf[128];//定义一个字符数组
	while(1){
		gets(buf);
		puts(buf);
		if(my_strcmp(buf,"LED1_ON")==0){
			led_ctl(1,1);
		}
		if(my_strcmp(buf,"LED1_OFF")==0){
			led_ctl(1,0);	
		}
		if(my_strcmp(buf,"LED2_ON")==0){
			led_ctl(2,1);
		}
		if(my_strcmp(buf,"LED2_OFF")==0){
			led_ctl(2,0);	
		}
		if(my_strcmp(buf,"LED3_ON")==0){
			led_ctl(3,1);
		}
		if(my_strcmp(buf,"LED3_OFF")==0){
			led_ctl(3,0);	
		}

	}
	return 0;
}

2.stm32U5开发板进行串口通信实验:

功能:电脑输入LED_ON点亮扩展版LED灯,输入LED_OFF熄灭扩展版LED灯

 main.c

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the System Power */
  SystemPower_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	char buf[32];//保存串口数据收发的容器
  while (1)
  {
		memset(buf,0,sizeof(buf));//进行数组清空
		HAL_UART_Receive(&huart1,(uint8_t *)buf,30,10000); //阻塞接收 
		if(strcmp(buf,"LED1_ON")==0){
			//打开led1
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,GPIO_PIN_SET);
		}
		if(strcmp(buf,"LED3_ON")==0){
			//打开led3
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
		}
		if(strcmp(buf,"LED_CYTLE_ON")==0){
			//循环打开
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
			HAL_Delay(1000);
		}
		if(strcmp(buf,"LED1_OFF")==0){
			//关闭led1
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,GPIO_PIN_RESET);
		}
		if(strcmp(buf,"LED3_OFF")==0){
			//关闭led3
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
		}
		if(strcmp(buf,"LED_CYTLE_OFF")==0){
			//关闭循环
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
		}
		if(strcmp(buf,"FAN_ON")==0){
			//打开风扇
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET);
		}
		if(strcmp(buf,"FAN_OFF")==0){
			//关闭风扇
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET);
		}
		if(strcmp(buf,"FENGMING_ON")==0){
			//打开蜂鸣器
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET);
		}
		if(strcmp(buf,"FENGMING_OFF")==0){
			//关闭蜂鸣器
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET);
		}
		HAL_UART_Transmit(&huart1,(uint8_t *)buf,sizeof(buf),5);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}