单片机串口控制

1.使用微控制器输入串口指令控制LED灯亮灭

main.c

cpp 复制代码
#include "uart4.h"


int main()
{
    led_init(); //初始化LED相关寄存器
    char buf[128];
    while(1){
        gets(buf);
        if(mystrcmp(buf,"LED1_on") == 0){
            led_ctl(1,1); //当在串口工具中输入"LED1_on"时控制LED1打开
            puts("灯已经打开\n");
        }else if(mystrcmp(buf,"LED1_off") == 0){
            led_ctl(1,0);当在串口工具中输入"LED1_off"时控制LED1关闭
            puts("灯已经关闭\n");
        }else{
            puts(buf);
        }
    }
}

uart4.h

cpp 复制代码
#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);
    //PG11
    GPIOG->MODER &= (~(0x3<<22));
    GPIOG->MODER |= (0x2<<22);
    GPIOG->AFRH &= (~(0xf<<12));
    GPIOG->AFRH |= (0x6<<12);

    //禁用串口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)
{
    //循环调用单个字符接收
    while(1)
    {
        *s=getchar();
        if(*s == '\r')
        {
            //s++;
            *s='\0';
            break;
        }
        putchar(*s);
        s++;
    }
   //*s = '\0';
   putchar('\n');
   putchar('\r');

    //等待读取到回车键\r,字符串接收

}

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

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

int mystrcmp(char *s1,char *s2)
{
    while(*s1==*s2)
	{
		if(*s1=='\0'||*s2=='\0')
		{
			break;
		}
		s1++;
		s2++;
	}
	return (*s1 - *s2);
}

void led_init()
{
	//GPIO初始化
	//外设时钟
	//*((unsigned int *)0x50000A28) |= (0x3 <<4);
	RCC->MP_AHB4ENSETR |= (0x3 <<4);

	//*((unsigned int *)0x50006000) &= (~(0x3 << 20));
	//*((unsigned int *)0x50006000) |= (0x1 << 20);
	GPIOE->MODER &= (~(0x3 << 20));
	GPIOE->MODER |= (0x1 << 20);

	//*((unsigned int *)0x50007000) &= (~(0x3 << 20));
	//*((unsigned int *)0x50007000) |= (0x1 << 20);
	GPIOF->MODER &= (~(0x3 << 20));
	GPIOF->MODER |= (0x1 << 20);


	//*((unsigned int *)0x50006000) &= (~(0x3 << 16));
	//*((unsigned int *)0x50006000) |= (0x1 << 16);
	GPIOE->MODER &= (~(0x3 << 16));
	GPIOE->MODER |= (0x1 << 16);

	//*((unsigned int *)0x50006004) &= (~(0x1 << 10));
	//*((unsigned int *)0x50007004) &= (~(0x1 << 10));
	//*((unsigned int *)0x50006004) &= (~(0x1 << 8));
	GPIOE->OTYPER &= (~(0x1 << 10));
	GPIOF->OTYPER &= (~(0x1 << 10));
	GPIOE->OTYPER &= (~(0x1 << 8));


	//*((unsigned int *)0x50006008) &= (~(0x3 << 20));
	//*((unsigned int *)0x50007008) &= (~(0x3 << 20));
	//*((unsigned int *)0x50006008) &= (~(0x3 << 16));
	GPIOE->OSPEEDR &= (~(0x3 << 20));
	GPIOF->OSPEEDR &= (~(0x3 << 20));
	GPIOE->OSPEEDR &= (~(0x3 << 16));



	//*((unsigned int *)0x5000600c) &= (~(0x3 << 20));
	//*((unsigned int *)0x5000700c) &= (~(0x3 << 20));
	//*((unsigned int *)0x5000600c) &= (~(0x3 << 16));
	GPIOE->PUPDR &= (~(0x3 << 20));
	GPIOF->PUPDR &= (~(0x3 << 20));
	GPIOE->PUPDR &= (~(0x3 << 16));
}

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;
	}
}

2.单片机串口控制风扇开关

cpp 复制代码
char buf[32];
  while (1)
  {
		memset(buf,0,sizeof(buf));
		HAL_UART_Receive(&huart1,(uint8_t *)buf,10,10000);
		if(strcmp(buf,"fan_on")==0){
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET);//风扇是PC6引脚
			printf("the fan is on\n\r");
		}else if(strcmp(buf,"fan_off")==0){
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET);
			printf("the fan is off\n\r");
		}else{
			HAL_UART_Transmit(&huart1,(uint8_t *)buf,strlen(buf),5);
		}
相关推荐
清风6666665 小时前
基于单片机与DAC0832的双路波形信号发生系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
azwsm7 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu10 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客10 小时前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭11 小时前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽11 小时前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊13 小时前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
进击的小头13 小时前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭13 小时前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
项目題供诗14 小时前
STM32-AD单通道&AD多通道(十九)
stm32·单片机·嵌入式硬件