实验要求:串口输入相应的命令控制对应的硬件进行工作 例如:
在串口工具输入LED1ON --------> LED1灯亮 PE10 在串口工具输入LED1OFF --------> LED1灯熄灭 在串口工具输入LED2ON --------> LED2灯亮 PF10 在串口工具输入LED2OFF --------> LED2灯熄灭 在串口工具输入LED3ON --------> LED3灯亮 PE8 在串口工具输入LED3OFF --------> LED3灯熄灭
结果:
实验:串口输入相应的命令控制对应的硬件进行工作
mian.c
#include "fun.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++)
;
}
char string[100] = {};
int main()
{
char *str;
rcc();
led_init();
hal_uart4_init();
cmd_t *p = 0;
while (1)
{
hal_put_string("led* on / led* off");
str = hal_get_string(string);
p = find_command(str);
if(p == 0)
{
hal_put_string("led* on / led* of");
}
else
{
p->gpio_write_p(p->gpio, p->pin, p->status);
}
}
return 0;
}
text.c
#include "fun.h"
//******RCC使能******
void rcc()
{
// GPIO
RCC->MP_AHB4ENSETR |= (0x3 << RCC_GPIOE_PIN_4);
RCC->MP_AHB4ENSETR |= (0x3 << RCC_GPIOF_PIN_5);
RCC->MP_APB1ENSETR |= (0x1 << RCC_GPIOG_PIN_6);
RCC->MP_APB1ENSETR |= (0x1 << RCC_GPIOB_PIN_1);
// UART4
RCC->MP_APB1ENSETR |= (0x1 << RCC_UART4_PIN16);
}
//==================================GPIO_start=====================================
//******初始化引脚函数(组编号,引脚号,初始化的值)******
void hal_gpio_init(gpio_t *gpiox, volatile unsigned int pin, gpio_init *init)
{
//******MODER******
gpiox->MODER &= (~(0x3 << (pin * 2)));
gpiox->MODER |= (init->moder << (pin * 2));
//*****OTYPER******
gpiox->OTYPER &= (~(0x1 << pin));
gpiox->OTYPER |= (init->otyper << pin);
//******OSPEEDT******
gpiox->OSPEEDR &= (~(0x3 << (pin * 2)));
gpiox->OSPEEDR |= (init->ospeedr << (pin * 2));
//******PUPDR******
gpiox->PUPDR &= (~(0x3 << (pin * 2)));
gpiox->PUPDR |= (init->pupdr << (pin * 2));
}
//******初始化四个通用寄存器的值******
void led_init()
{
gpio_init p;
p.moder = Output;
p.otyper = Push_pull;
p.ospeedr = Low;
p.pupdr = NO_pull_up_pull_down;
hal_gpio_init(GPIOE, GPIO_PIN_10, &p);
hal_gpio_init(GPIOF, GPIO_PIN_10, &p);
hal_gpio_init(GPIOE, GPIO_PIN_8, &p);
}
//******初始化引脚的高低电平(组编号,引脚号,操作的值)******
void hal_gpio_write(gpio_t *gpiox, volatile unsigned int pin, gpio_odr odr)
{
if (odr == ZERO)
{
gpiox->ODR &= (~(0x1 << pin));
}
else
{
gpiox->ODR |= (0x1 << pin);
}
}
//==================================GPIO_END=====================================
//==================================UART4_start===================================
// 初始化引脚函数
void hal_uart4_init()
{
// ******GPIO_MODER设置为复用模式******
// UART4_TX PG11
GPIOG->MODER &= (~(0x3 << 22));
GPIOG->MODER |= (0x1 << 23);
// UART4_RX PB2
GPIOB->MODER &= (~(0x3 << 4));
GPIOB->MODER |= (0x1 << 5);
// AF6;
GPIOG->AFRH &= (~(0xf << 12));
GPIOG->AFRH |= (0x3 << 13);
// AF8
GPIOG->AFRL &= (~(0xf << 8));
GPIOG->AFRL |= (0x1 << 11);
//******8N1 115200 对应位使能******
// 先把UE使能关闭
if (USART4->CR1 & 0x1)
{
delay_ms(500);
USART4->CR1 &= (~(0x1 << 0));
}
// ******设置UART4串口 1位起始位 8位数据位 1位停止位 无奇偶校验位******
// 1位起始位 8位数据位
USART4->CR1 &= (~(0x1 << 28));
USART4->CR1 &= (~(0x1 << 12));
// 1位停止位
USART4->CR2 &= (~(0x3 << 12));
// 无奇偶校验位
USART4->CR1 &= (~(0x1 << 10));
// 16倍采样频率
USART4->CR1 &= (~(0x1 << 15));
// 设置串口不分频
USART4->PRESC &= (~(0xf << 0));
// 设置串口波特率为115200 BRR = 0x22b
USART4->BRR |= 0x22b;
// 发送使能
USART4->CR1 |= (0x1 << 3);
// 接收使能
USART4->CR1 |= (0x1 << 2);
// 最后才能UE使能
USART4->CR1 |= (0x1 << 0);
}
//==================================UART4_end=====================================
//****************************串口的接收发送字符_start*****************************
// 发送一个字符
void hal_put_char(const char str)
{
// 判断发送数据寄存器是否为空 ISR[7]
// 读0:发送数据寄存器满,需要等待
// 读1:发送数据寄存器为空,发送下一个字节
while (!(USART4->ISR & (0X1 << 7)))
;
USART4->TDR = str;
while (!(USART4->ISR & (0x1 << 6)))
;
}
// 发送一个字符串
void hal_put_string(const char *string)
{
// 判断是否为\0
// 一个一个字符发送
while (*string)
{
hal_put_char(*string++);
}
hal_put_char('\n');
hal_put_char('\r');
}
// 接收一个字符
char hal_get_char()
{
// 定一个变量,用来接收的数据
char ch;
while (!(USART4->ISR & (0x1 << 5)))
;
ch = USART4->RDR;
return ch;
}
// 接收一个字符串
char buf[100] = {};
char *hal_get_string()
{
// for循环
// 判断键盘回车是否按下 '\r'
int i = 0;
for (i = 0; i < 99; i++)
{
// 接收一个字符
buf[i] = hal_get_char();
// 回显到串口工具 发送一个字符
hal_put_char(buf[i]);
if (buf[i] == '\r')
break;
}
buf[i] = '\0';
hal_put_char('\n');
return buf;
}
//****************************串口的接收发送字符_end*****************************
// 初始化结构体
cmd_t arr[6] = {
[0] = {
.cmd_arr = "led1on",
.gpio = GPIOE,
.pin = GPIO_PIN_10,
.status = ONE,
.gpio_write_p = hal_gpio_write,
},
[1] = {
.cmd_arr = "led1off",
.gpio = GPIOE,
.pin = GPIO_PIN_10,
.status = ZERO,
.gpio_write_p = hal_gpio_write,
},
[2] = {
.cmd_arr = "led2on",
.gpio = GPIOF,
.pin = GPIO_PIN_10,
.status = ONE,
.gpio_write_p = hal_gpio_write,
},
[3] = {
.cmd_arr = "led2off",
.gpio = GPIOF,
.pin = GPIO_PIN_10,
.status = ZERO,
.gpio_write_p = hal_gpio_write,
},
[4] = {
.cmd_arr = "led3on",
.gpio = GPIOE,
.pin = GPIO_PIN_8,
.status = ONE,
.gpio_write_p = hal_gpio_write,
},
[5] = {
.cmd_arr = "led3off",
.gpio = GPIOE,
.pin = GPIO_PIN_8,
.status = ZERO,
.gpio_write_p = hal_gpio_write,
}};
// My_strcmp
int My_strcmp(const char *str1, const char *str2)
{
while (*str1)
{
if (*str1 != *str2)
return (*str1 - *str2);
str1++;
str2++;
}
return (*str1 - *str2);
}
// 查找输入命令函数
cmd_t *find_command(const char *str)
{
for (int i = 0; i < 6; i++)
{
if (My_strcmp(str, arr[i].cmd_arr) == 0)
return &arr[i];
}
// 因为NULL是空指针,裸机里面是没有的 所以返回0
return 0;
}
fun.h
#ifndef __FUN_H__
#define __FUN_H__
#include "stm32mp1xx_uart.h" // 调用UART封装库
#include "stm32mp1xx_gpio.h" // 调用GPIO封装库
#include "stm32mp1xx_rcc.h" // 调用RCC封装库
#include "strcmp.h" //调用自己封装的strcmp函数
// GPIO
//===========================================================================================
//***********GPIO引脚************
#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
// RCC用
#define RCC_GPIOA_PIN_0 0
#define RCC_GPIOB_PIN_1 1
#define RCC_GPIOC_PIN_2 2
#define RCC_GPIOD_PIN_3 3
#define RCC_GPIOE_PIN_4 4
#define RCC_GPIOF_PIN_5 5
#define RCC_GPIOG_PIN_6 6
#define RCC_GPIOH_PIN_7 7
#define RCC_GPIOI_PIN_8 8
#define RCC_GPIOJ_PIN_9 9
#define RCC_GPIOK_PIN_10 10
#define RCC_UART4_PIN16 16
//******四个通用寄存器(MODER、OTYPER,OSPEEDR、PUPDR)******
// MODER
typedef enum
{
InputT,
Output,
Fcion,
Analog
} gpio_moder;
// OTYPER
typedef enum
{
Push_pull,
Open_drain,
} gpio_otyper;
// OPEEDR
typedef enum
{
Low,
Medium,
High,
Very_high
} gpio_ospeedr;
// PUPDR
typedef enum
{
NO_pull_up_pull_down,
Pull_up,
Pull_down,
Reserved
} gpio_pupdr;
// ODR
typedef enum
{
ZERO,
ONE
} gpio_odr;
typedef struct
{
gpio_moder moder;
gpio_otyper otyper;
gpio_ospeedr ospeedr;
gpio_pupdr pupdr;
} gpio_init;
//******RCC使能******
void rcc();
// 初始化引脚函数(组编号,引脚号,初始化的值)
void hal_gpio_init(gpio_t *gpiox, volatile unsigned int pin, gpio_init *init);
// 初始化引脚的高低电平(组编号,引脚号,操作的值)
void hal_gpio_write(gpio_t *gpiox, volatile unsigned int pin, gpio_odr odr);
//===========================================================================================
//初始化四个通用寄存器的值
void led_init();
// 发送一个字符
void hal_put_char(const char str);
// 发送一个字符串
void hal_put_string(const char *string);
// 接收一个字符
char hal_get_char();
// 接收一个字符串
char *hal_get_string();
// usart4
void hal_uart4_init();
void delay_ms(int ms);
//结构体封装
typedef struct
{
char *cmd_arr; // 命令字符串
gpio_t *gpio; // gpio组号
unsigned int pin; // 操作引脚编号
gpio_odr status; // LED灯状态
void (*gpio_write_p)(gpio_t *gpio, unsigned int pin, gpio_odr status);
} cmd_t;
//查找输入命令函数
cmd_t* find_command(const char* str);
//My_strcmp
int My_strcmp(const char *str1, const char *str2);
#endif