1.11 LED灯点亮&串口解析器

LED点灯实验

一.电路图:

 

三极管:

                                   

 

NPN类型:

                      

   PNP类型:

 

 

          

NPN类型当基极为高电平时,集电极和发射极导通

PNP类型当基极为低电平时,集电极和发射极导通

由电路图可知LED电路图中三极管为NPN类型,只有当基极为高电平时,集电极和发射极导通,LED亮起。因此LED亮起为高电平,LED熄灭为低电平

LED1----PE10

LED2----PF10

LED3----PE8

  • 分析RCC章节

作用:使能GPIO

RCC在AHB4总线上(芯片手册第二章),通过RCC_MP_AHB4ENSETR寄存器使能GPIOE组和GPIOF组相关控制器

  • 分析GPIO章节

GPIO框图

 

  1. MOS管:栅极为低电平时,源极和漏极导通
  1. MOS管:栅极为高电平时,源极和漏极导通

GPIO相关寄存器

GPIO_MODER: 选择输出模式

GPIO_OTYPER:选择输出类型

GPIO_SPEEDR:选择输出速率

GPIO_PUPDR:选择是否需要上下拉电阻

GPIO_ODR:控制输出高电平还是低电平

代码:

gpio.h:

#ifndef __GPIO_H__
#define __GPIO_H__

//寄存器封装
typedef struct{
	volatile unsigned int MODER;
	volatile unsigned int OTYPER;
	volatile unsigned int OSPEEDR;
	volatile unsigned int PUPDR;
	volatile unsigned int IDR;
	volatile unsigned int ODR;
}gpio_t;

#define GPIOE ((gpio_t*)0x50006000)
#define GPIOF ((gpio_t*)0x50007000)
#define RCC_AHB4_ENSETR (*(volatile unsigned int*)0x50000A28)
//封装引脚
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15

//模式寄存器封装
typedef enum{
	INPUT,
	OUTPUT,
	ALT,
	ANALOG
}gpio_moder_t;

//输出类型寄存器封装
typedef enum{
	PP,
	OD
}gpio_otyper_t;

//输出速率寄存器封装
typedef enum{
	LOW,
	MED,
	HIGH,
	VERY_HIGH
}gpio_ospeedr_t;

//是否需要上下拉电阻封装
typedef enum{
	NO_PUPD,
	PU,
	PD
}gpio_pupdr_t;

//输出高低电平寄存器封装
typedef enum{
	GPIO_RESET,
	GPIO_SET
}gpio_status_t;

//封装初始化结构体
typedef struct{
	gpio_moder_t moder; //模式 
	gpio_otyper_t otyper; //输出类型 
	gpio_ospeedr_t speed;//速率
	gpio_pupdr_t pupdr; //是否需要上下拉电阻 
}gpio_init_t;

//函数功能:初始化GPIO(根据参数初始化不同LED)
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin);

//函数功能:操作GPIO引脚,实现LED灯亮灭
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status);

#endif

gpio.c:

#include "gpio.h"

void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin)
{
	gpiox->MODER&=(~(0x3<<(pin*2)));//设置IO口模式为输出模式
	gpiox->MODER|=(init->moder)<<(pin*2);

	gpiox->OTYPER&=~(0x1<<(pin));//设置输出类型为推挽类型
	gpiox->OTYPER|=(init->otyper)<<(pin);

	gpiox->OSPEEDR&=~(0x3<<(pin*2));//设置输出速率为低速
	gpiox->OSPEEDR|=(init->otyper)<<(pin*2);

	gpiox->PUPDR&=~(0x3<<(pin*2));//设置不需要上下拉电阻
	gpiox->PUPDR|=(init->pupdr)<<(pin*2);

}


void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status)
{
	if(status==GPIO_SET){  //判断状态
		gpiox->ODR|=(0x1<<pin);//写入高电平
	}else{
		gpiox->ODR&=~(0x1<<pin);//写入低电平
	}
}

main.c:

#include "gpio.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}

void led_init()
{
	//1.时钟使能
	RCC_AHB4_ENSETR|=(0x3<<4);	
	//2.初始化结构体
	gpio_init_t init={OUTPUT,PP,LOW,NO_PUPD};

	//3.调用gpio初始化函数
	hal_gpio_init(GPIOE,&init,10);
	hal_gpio_init(GPIOF,&init,10);
	hal_gpio_init(GPIOE,&init,8);
}

int main()
{
	led_init();
	while(1)
	{
		hal_gpio_write(GPIOE,10,GPIO_SET);
		delay_ms(1000);
		hal_gpio_write(GPIOE,10,GPIO_RESET);
		
		hal_gpio_write(GPIOF,10,GPIO_SET);
		delay_ms(1000);
		hal_gpio_write(GPIOF,10,GPIO_RESET);
		
		hal_gpio_write(GPIOE,8,GPIO_SET);
		delay_ms(1000);
		hal_gpio_write(GPIOE,8,GPIO_RESET);
	}
	return 0;
}

串口解析器

led.h

#ifndef __LED_H__
#define __LED_H__
#include "../common/include/stm32mp1xx_gpio.h"
/*
//LED1初始化
void led1_init();
//LED1点亮
void led1_on();
//LED1熄灭
void led1_off();
*/
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15

typedef enum{
	GPIO_RESET,
	GPIO_SET
}gpio_status_t;


typedef struct{
	char* cmd_str;           //字符串
	gpio_t* gpiox;            //GPIO组		
	unsigned int pin;		//引脚
	gpio_status_t stat; 			//LED状态
	void (*gpio_write_p)(gpio_t* gpiox,unsigned int pin,gpio_status_t stat);	
}cmd_t;   


void hal_gpio_init();

void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t stat);

void put_char(const char c);

char get_char();

char* get_string();

cmd_t* cmp_str(char* str);

int my_strcmp(char* str1 ,char* str2);

void put_string(char* string);


#endif

led.c

#include "../include/led.h"
#include "../common/include/stm32mp1xx_gpio.h"
#include "../common/include/stm32mp1xx_rcc.h"
#include "../common/include/stm32mp1xx_uart.h"
extern void printf(const char *fmt, ...);

//初始化/
void hal_gpio_init(){
	RCC->MP_AHB4ENSETR|=0x1<<4;
	RCC->MP_AHB4ENSETR|=0x1<<5; 


	//LED1----PE10
	GPIOE->MODER&=(~(0x3)<<20);
	GPIOE->MODER|=(0x1<<20);
	
	GPIOE->OTYPER&=(~(0x1<<10));

	GPIOE->OSPEEDR&=(~(0x3<<20));

	GPIOE->PUPDR&=(~(0x3<<20));

	//LED2----PF10
	GPIOF->MODER&=(~(0x3)<<20);
	GPIOF->MODER|=(0x1<<20);
	
	GPIOF->OTYPER&=(~(0x1<<10));

	GPIOF->OSPEEDR&=(~(0x3<<20));

	GPIOF->PUPDR&=(~(0x3<<20));

	//LED3----PE8
	GPIOE->MODER&=(~(0x3)<<16);
	GPIOE->MODER|=(0x1<<16);
	
	GPIOE->OTYPER&=(~(0x1<<8));

	GPIOE->OSPEEDR&=(~(0x3<<16));

	GPIOE->PUPDR&=(~(0x3<<16));

	//UART
	RCC->MP_AHB4ENSETR |= (0x1 << 1);
    RCC->MP_AHB4ENSETR |= (0x1 << 6);

    // 使能UART控制器的时钟
    RCC->MP_APB1ENSETR |= (0x1 << 16);

    /*******GPIO章节初始化*******/
    // 设置PG11为复用模式
    GPIOG->MODER &= (~(0x3 << 22));
    GPIOG->MODER |= (0x2 << 22);

    //设置PB2为复用模式
    GPIOB->MODER &= (~(0x3 << 4));
    GPIOB->MODER |= (0x2 << 4);

    //设置PG11为UART4_TX复用功能
    GPIOG->AFRH &= (~(0xf << 12));
    GPIOG->AFRH |= (0x6 << 12);

    //设置PB2为UART4_RX复用功能
    GPIOB->AFRL &= (~(0xf << 8));
    GPIOB->AFRL |= (0x8 << 8);

    /*******UART章节初始化*******/
    //设置UART4传输数据宽度为8位
    USART4->CR1 &= (~(0x1 << 28));
    USART4->CR1 &= (~(0x1 << 12));

    //设置UART4串口16倍采样率
    USART4->CR1 &= (~(0x1 << 15));

    //设置UART4串口无奇偶校验位
    USART4->CR1 &= (~(0x1 << 10));

    //设置UART4串口发送寄存器和接收寄存器使能
    USART4->CR1 |= (0x3 << 2);

    //设置UART4串口1位停止位
    USART4->CR2 &= (~(0x3 << 12));

    //设置UART4串口不分频
    USART4->PRESC &= ~0xf;

    //设置UART4串口波特率为115200
    USART4->BRR &= ~0xffff;
    USART4->BRR |= 0x22b;

    //设置UART4串口使能
    USART4->CR1 |= 0x1;



}


//初始化结构体
cmd_t cmd_arr[6]={
	[0]={
		.cmd_str="LED1ON",
		.gpiox=GPIOE,
		.pin=GPIO_PIN_10,
		.stat=GPIO_SET,
		.gpio_write_p=hal_gpio_write,
	},
	[1]={
		.cmd_str="LED1OFF",
		.gpiox=GPIOE,
		.pin=GPIO_PIN_10,
		.stat=GPIO_RESET,
		.gpio_write_p=hal_gpio_write,
	},
	[2]={
		.cmd_str="LED2ON",
		.gpiox=GPIOF,
		.pin=GPIO_PIN_10,
		.stat=GPIO_SET,
		.gpio_write_p=hal_gpio_write,
	},
	[3]={
		.cmd_str="LED2OFF",
		.gpiox=GPIOF,
		.pin=GPIO_PIN_10,
		.stat=GPIO_RESET,
		.gpio_write_p=hal_gpio_write,
	},
	[4]={
		.cmd_str="LED3ON",
		.gpiox=GPIOE,
		.pin=GPIO_PIN_8,
		.stat=GPIO_SET,
		.gpio_write_p=hal_gpio_write,
	},
	[5]={
		.cmd_str="LED3OFF",
		.gpiox=GPIOE,
		.pin=GPIO_PIN_8,
		.stat=GPIO_RESET,
		.gpio_write_p=hal_gpio_write,
	}

};



// 2.发送一个字符
void put_char(const char str)
{
    while (!(USART4->ISR & (0x1 << 7)));

    USART4->TDR = str;
    while (!(USART4->ISR & (0x1 << 6)));
}

// 3.发送一个字符串
void put_string( char *str)
{
    while (*str)
    {
        put_char(*str++);
    }
    put_char('\n');
    put_char('\r');
}

// 4.接收一个字符
char get_char()
{
    char ch;
    while (!(USART4->ISR & (0x1 << 5)));

    ch = USART4->RDR;
    return ch;
}

char buffer[50] = {0};
char *get_string()
{
    unsigned int i;
    for (i = 0; i < 49; i++)
    {
        buffer[i] = get_char();
        put_char(buffer[i]);
        if (buffer[i] == '\r')
            break;
    }
    buffer[i] = '\0';
    put_char('\n');
    return buffer;
}

int my_strcmp(char* str1,char* str2){           //比较字符串

while ((*str1 != '\0') && (*str1 == *str2))//判断字符串是否结束。
    {
        str1++;
        str2++;//
    }
    int t;
    t = *str1 - *str2;//比较对应字符大小。
    if (t == 0)
        printf("same string\n");
    else if (t > 0)
        printf("str1 is bigger\n");
    else
        printf("str2 is bigger\n");
    return t;//若相等返回0,前者大返回正值,反之则负。
}


cmd_t* cmp_str(char* str)            //循环比较字符串和结构体数组中的字符串
{
	for(unsigned int i=0;i<6;i++){
		if(my_strcmp(str,cmd_arr[i].cmd_str)==0){
			return &cmd_arr[i];
		}
	}
	return 0;
}

void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status)
{
	if(status==GPIO_SET){
		gpiox->ODR|=(0x1<<pin);
	}else{
		gpiox->ODR&=~(0x1<<pin);	
	}
}

main.c

#include "led.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}


int main()
{
	hal_gpio_init();
	char* string="";
	cmd_t *p;

	while(1)
	{
		string=get_string();
		printf("%s\n",string);
		p=cmp_str(string);
		if(p==0){
			put_char('n');   //测试
		}else{
			put_char('y');    //测试

			p->gpio_write_p(p->gpiox,p->pin,p->stat);    
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值