head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include "../common/include/stm32mp1xx_gpio.h"
#include "../common/include/stm32mp1xx_rcc.h"
#include "../common/include/stm32mp1xx_uart.h"
// 引脚编号封装
#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
// MODER模式寄存器
typedef enum
{
INPUT,
OUTPUT,
ALT,
ANALOG
} gpio_moder_t;
// OTYPER输出模式寄存器
typedef enum
{
PP,
OD
} gpio_otyper_t;
// OSPEEDR输出速率寄存器
typedef enum
{
LS,
MS,
HS,
VHS
} gpio_ospeedr_t;
// PUPDR是否需要上下拉电阻寄存器
typedef enum
{
NPP,
PU,
PD,
RES
} gpio_pupdr_t;
// ODR输出高低电平寄存器
typedef enum
{
RES_T,
SET_T
} gpio_status_t;
// 将重定义的枚举类型寄存器封装到结构体中
typedef struct
{
gpio_moder_t moder; // 模式寄存器
gpio_otyper_t otyper; // 输出类型寄存器
gpio_ospeedr_t ospeedr; // 输出速率寄存器
gpio_pupdr_t pupdr; // 是否需要上下拉电阻寄存器
} gpio_init_t;
// 将指令信息封装到结构体中
typedef struct
{
char *cmd_arr; // 命令字符串
gpio_t *gpiox; // gpio组号
unsigned int pin; // 对应引脚编号
gpio_status_t status; // 对应引脚状态
void (*gpio_write)(gpio_t *gpiox, gpio_status_t status, unsigned int pin);
} cmd_t;
// GPIO引脚初始化函数 PE10 PF10 PE8
// void hal_gpio_init(GPIO组编号,引脚编号,初始化的值)
void hal_gpio_init(gpio_t *gpiox, unsigned int pin, gpio_init_t *gpio_init);
// GPIO引脚初始化函数 写0:熄灭 写1:点亮
// void hal_gpio_writr(GPIO组编号,引脚编号,操作的值)
void hal_gpio_write(gpio_t *gpiox, unsigned int pin, gpio_status_t status);
// led1 led2 led3初始化
void led_init();
// 串口初始化函数
void uart4_init();
// 发送一个字符
void hal_put_char(const char str);
// 发送一个字符串
void hal_put_string(const char *string);
// 接收一个字符
char hal_get_char();
// 接收一个字符串
char *hal_get_string();
// 字符串比较函数
int my_strcmp(const char *str1, const char *str2);
// 查找指令函数
cmd_t *find_command(const char *str);
#endif
test.c
#include "../include/head.h"
cmd_t arr[6] = {
[0] = {
.cmd_arr = "led1on",
.gpiox = GPIOE,
.pin = GPIO_PIN_10,
.status = SET_T,
.gpio_write = hal_gpio_write,
},
[1] = {
.cmd_arr = "led1off",
.gpiox = GPIOE,
.pin = GPIO_PIN_10,
.status = RES_T,
.gpio_write = hal_gpio_write,
},
[2] = {
.cmd_arr = "led2on",
.gpiox = GPIOF,
.pin = GPIO_PIN_10,
.status = SET_T,
.gpio_write = hal_gpio_write,
},
[3] = {
.cmd_arr = "led2off",
.gpiox = GPIOF,
.pin = GPIO_PIN_10,
.status = RES_T,
.gpio_write = hal_gpio_write,
},
[4] = {
.cmd_arr = "led3on",
.gpiox = GPIOE,
.pin = GPIO_PIN_8,
.status = SET_T,
.gpio_write = hal_gpio_write,
},
[5] = {
.cmd_arr = "led3off",
.gpiox = GPIOE,
.pin = GPIO_PIN_8,
.status = RES_T,
.gpio_write = hal_gpio_write,
},
};
// LED GPIO初始化函数
void hal_gpio_init(gpio_t *gpiox, unsigned int pin, gpio_init_t *gpio_init)
{
// 设置gpio引脚模式 MODER 每两位管理一个引脚
gpiox->MODER &= (~(0x3 << (pin * 2)));
gpiox->MODER |= (gpio_init->moder << (pin * 2));
// 设置gpio引脚输出类型 OTYPER 每一位管理一个引脚
gpiox->OTYPER &= (~(0x1 << pin));
gpiox->OSPEEDR |= (gpio_init->otyper << (pin));
// 设置gpio引脚输出速率
gpiox->OSPEEDR &= (~(0x3 << (pin * 2)));
gpiox->OSPEEDR |= (gpio_init->ospeedr << (pin * 2));
// 设置gpio引脚禁止上下拉电阻
gpiox->PUPDR &= (~(0x3 << (pin * 2)));
gpiox->PUPDR |= (gpio_init->pupdr << (pin * 2));
}
// LED灯亮灭控制函数
void hal_gpio_write(gpio_t *gpiox, unsigned int pin, gpio_status_t status)
{
if (status == RES_T)
{
gpiox->ODR &= (~(0x1 << pin));
}
else
{
gpiox->ODR |= (0x1 << pin);
}
}
// led1 led2 led3初始化
void led_init()
{
gpio_init_t init;
// 初始化时钟GPIOE组和GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x3 << 4);
// 结构体进行初始化
init.moder = OUTPUT;
init.otyper = PP;
init.ospeedr = LS;
init.pupdr = NPP;
hal_gpio_init(GPIOE, GPIO_PIN_10, &init);
hal_gpio_init(GPIOF, GPIO_PIN_10, &init);
hal_gpio_init(GPIOE, GPIO_PIN_8, &init);
}
// uart初始化函数
void uart4_init()
{
//**************RCC章节****************//
// 1.使能GPIOB组控制器
RCC->MP_AHB4ENSETR |= (0x1 << 1);
// 2.使能GPIOG组控制器
RCC->MP_AHB4ENSETR |= (0x1 << 6);
// 3.使能UART4组控制器
RCC->MP_APB1ENSETR |= (0x1 << 16);
//**************GPIO章节**************//
// GPIOB2 设置为复用功能
GPIOB->MODER &= (~(0x3 << 4));
GPIOB->MODER |= (0x1 << 5);
GPIOB->AFRL &= (~(0xF << 8));
GPIOB->AFRL |= (0x1 << 11);
// GPIOG11 设置为复用功能
GPIOG->MODER &= (~(0x3 << 22));
GPIOG->MODER |= (0x1 << 23);
GPIOG->AFRH &= (~(0xF << 12));
GPIOG->AFRH |= (0x3 << 13);
//*************UART4章节*************//
// 设置数据长度为8位 USART_CR1
USART4->CR1 &= (~(0x1 << 28));
USART4->CR1 &= (~(0x1 << 12));
USART4->CR1 &= (~(0x1 << 10));
// 采样率为16位
USART4->CR1 &= (~(0x1 << 15));
// 设置串口不分频
USART4->PRESC &= (~(0xF << 0));
// 设置波特率为115200bps
USART4->BRR = 0x22B;
// 停止位1位
USART4->CR2 &= (~(0x3 << 12));
// 使能USART串口
USART4->CR1 |= 0x1;
// 使能USART的发送功能
USART4->CR1 |= (0x1 << 3);
// 使能USART的接收功能
USART4->CR1 |= (0x1 << 2);
}
// 发送一个字符
void hal_put_char(const char str)
{
// 判断发送数据寄存器是否为空 ISR[7]
// 读0:发送数据寄存器满,需要等待
// 读1:发送数据寄存器为空,发送下一个字节
while (!(USART4->ISR & (0x1 << 7)))
;
// 将数据赋值给发送数据寄存器
USART4->TDR = str;
if (str == '\n')
{
hal_put_char('\r');
}
// 判断发送是否完成
while (!(USART4->ISR & (0x1 << 6)))
;
}
// 发送一个字符串
void hal_put_string(const char *string)
{
// 判断是否为\0
while (*string != '\0')
{
hal_put_char(*string++); // 发送每个字符
}
hal_put_char('\n'); // 光标移到下一行
}
// 接收一个字符
char hal_get_char()
{
// 定义一个变量,用来接收数据
char ch;
while (!(USART4->ISR & (0x1 << 5)))
;
ch = (char)USART4->RDR;
return ch;
}
// 接收一个字符串
char str[64] = " "; // 定义一个字符数组存放字符串
char *hal_get_string()
{
unsigned int i; // 定义无符号整型i用于for循环
// for循环
for (i = 0; i < sizeof(str); i++)
{
str[i] = hal_get_char();
hal_put_char(str[i]); // 回显
// 判断键盘回车是否按下'\r'
if (str[i] == '\r')
{
break;
}
}
str[i] = '\0'; // 字符串末尾补'\0'
hal_put_char('\n'); // 光标移到下一行
return str;
}
// 字符串比较函数
int my_strcmp(const char *str1, const char *str2)
{
while (*str1 != '\0' || *str2 != '\0')
{
if (*str1 != *str2)
{
return -1;
}
str1++;
str2++;
}
return 0;
}
// 查找指令函数
cmd_t *find_command(const char *buf)
{
unsigned int i;
for (i = 0; i < 6; i++)
{
if (0 == (my_strcmp(buf, arr[i].cmd_arr)))
{
return &arr[i];
}
}
return 0;
}
main.c
#include "./include/head.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()
{
led_init(); // LED123初始化
uart4_init(); // uart初始化
while (1)
{
char *buffer = hal_get_string();
cmd_t *p;
p = find_command(buffer);
if (p == 0)
{
hal_put_string("************ error command ***************");
}
else
{
p->gpio_write(p->gpiox, p->pin, p->status);
}
}
return 0;
}
运行结果: