实验1
键盘输入一个字符’a’,串口工具显示’b’
uart4.h
#ifndef __UART4_H__
#define __UART4_H__
#include"stm32mp1xx_rcc.h"
#include"stm32mp1xx_gpio.h"
#include"stm32mp1xx_uart.h"
#define RCC_MP_APB1ENSETR (*(volatile unsigned int*)0x50000A00)
#define RCC_MP_AHB4ENSETR (*(volatile unsigned int*)0x50000A28)
//初始化相关操作
void hal_uart_init();
//发送一个字符
void hal_put_char(char ch);
//发送一个字符串
void hal_put_string(char* str);
//接收一个字符
char hal_get_char();
//接收一个字符串
char* hal_get_string();
#endif
uart4.c
#include"uart4.h"
//初始化相关操作
void hal_uart_init()
{
/*****************RCC章节初始化*****************/
//使能GPIOG组控制器 MP_APB4ENSETR[6] = 1
RCC->MP_AHB4ENSETR |= (0x1<<6);
//使能GPIOB组控制器 MP_APB4ENSETR[1] = 1
RCC->MP_AHB4ENSETR |= (0x1<<1);
//使能UART4组控制器 MP_APB1ENSETR[16] = 1
RCC->MP_APB1ENSETR |= (0x1<<16);
/*****************GPIO章节初始化*****************/
//设置PG11引脚为复用功能模式 MODER[23:22]=10
GPIOG->MODER &= (~(0x3 << 22));
GPIOG->MODER |= (0x1 << 23);
//设置PG11引脚的复用功能 GPIOG_AFRH[15:12] = 0110
GPIOG->AFRH &= (~(0xf << 12)); //注意此处为AFRH
GPIOG->AFRH |= (0x3 << 13);
//设置PB2引脚为复用功能模式 MODER[5:4]=10
//GPIOB->MODER &= (~(0x3 << 4));
GPIOB->MODER &= (~(0x1 << 4));
GPIOB->MODER |= (0x1 << 5);
//设置PB2引脚的复用功能 GPIOB_AFRL[11:8] = 1000
//GPIOB->AFRL &= (~(0x7 << 8));
GPIOB->AFRL &= (~(0xF << 8));
GPIOB->AFRL |= (0x1 << 11);
/*****************USART章节初始化*****************/
//0.设置串口不使能 UE: CR1[0] = 0
USART4->CR1 &= (~(0x1 << 0)); //error
//1.-设置1位起始位,8位数据位 M1,M0: CR1[28][12] = 00
USART4->CR1 &= (~(0x1 << 12));
USART4->CR1 &= (~(0x1 << 28));
//2.-无奇偶校验位 PCE: CR1[10] = 0
USART4->CR1 &= (~(0x1 << 10));
//3.-设置1位停止位 CR2[13][12] = 00
USART4->CR2 &= (~(0x3 << 12));
//4.-设置串口16倍采样率 OVER8: CR1[15] = 0
USART4->CR1 &= (~(0x1 << 15));
//5.-串口不分频 PRESC[3:0] = 0000
USART4->PRESC &= (~(0xF << 0));
//6.-设置串口波特率为115200 BRR = 0x22B
USART4->BRR = 0x22B;
//7.-设置串口发送器使能 TE: CR1[3] = 1 //err
USART4->CR1 |= (0x1 << 3);
//8.-设置串口接收器使能 RE: CR1[2] = 1
USART4->CR1 |= (0x1 << 2);
//9.-设置串口使能 UE: CR1[0] = 1
USART4->CR1 |= (0x1 << 0);
}
//发送一个字符
void hal_put_char(const char ch)
{
//1.判断发送数据寄存器的TXE(ISR[7])位是否为空
//读0:为满,继续等待,读1:为空
while(!(USART4->ISR & (0x1 << 7)));
//2.将发送的内容,赋值给发送数据寄存器
USART4->TDR = ch;
//3.判断一帧数据是否发送完成 TC(ISR[6])
//ISR[6] == 0:没有发送完成,继续等待 1:发送完成
while(!(USART4->ISR & (0x1 << 6)));
}
//发送一个字符串
void hal_put_string(char* str)
{
int i = 0;
//1.判断是否为字符串结束标识'\0'
while(str[i] != 0)
{
while(!(USART4->ISR & (0x1 << 7))); //为满则一直等待
//2.一个一个字符发送
hal_put_char(str[i]);
while(!(USART4->ISR & (0x1 << 6)));
i++;
}
}
//接收一个字符
char hal_get_char()
{
//1.判断接收数据寄存器是否接收到数据 ISR[5]
while(!(USART4->ISR & (0x1 << 5)));
//2.将接收数据寄存器的内容读取出来
return (char)(USART4->RDR);
}
//接收一个字符串
char* hal_get_string()
{
int i = 0;
static char buf[128];
while('\r' != (buf[i] = hal_get_char()))
{
i++;
}
buf[i] = 0;
return buf;
}
main.c
#include "uart4.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()
{
char ch;
char str[] = " hello world";
hal_uart_init();
/*原始调试*/
hal_put_string(str);
//换到下一行的首字符进行输入
hal_put_char('\n');
hal_put_char('\r');
while(1)
{
ch = hal_get_char();
hal_put_char(ch+1);
}
return 0;
}
作业1结果
实验2
实现现象:键盘输入一个字符串,串口工具回显输入的字符串
uart4.h
#ifndef __UART4_H__
#define __UART4_H__![请添加图片描述](https://img-blog.csdnimg.cn/36d42fd305d44231b669cc145916f1bd.png)
#include"stm32mp1xx_rcc.h"
#include"stm32mp1xx_gpio.h"
#include"stm32mp1xx_uart.h"
#define RCC_MP_APB1ENSETR (*(volatile unsigned int*)0x50000A00)
#define RCC_MP_AHB4ENSETR (*(volatile unsigned int*)0x50000A28)
//初始化相关操作
void hal_uart_init();
//发送一个字符
void hal_put_char(char ch);
//发送一个字符串
void hal_put_string(char* str);
//接收一个字符
char hal_get_char();
//接收一个字符串
char* hal_get_string();
//接收单个字符并立即回显,在用户输入回车后,将本行数据再次进行输出
char hal_get_chars();
#endif
uart4.c
#include"uart4.h"
//初始化相关操作
void hal_uart_init()
{
/*****************RCC章节初始化*****************/
//使能GPIOG组控制器 MP_APB4ENSETR[6] = 1
RCC->MP_AHB4ENSETR |= (0x1<<6);
//使能GPIOB组控制器 MP_APB4ENSETR[1] = 1
RCC->MP_AHB4ENSETR |= (0x1<<1);
//使能UART4组控制器 MP_APB1ENSETR[16] = 1
RCC->MP_APB1ENSETR |= (0x1<<16);
/*****************GPIO章节初始化*****************/
//设置PG11引脚为复用功能模式 MODER[23:22]=10
GPIOG->MODER &= (~(0x3 << 22));
GPIOG->MODER |= (0x1 << 23);
//设置PG11引脚的复用功能 GPIOG_AFRH[15:12] = 0110
GPIOG->AFRH &= (~(0xf << 12)); //注意此处为AFRH
GPIOG->AFRH |= (0x3 << 13);
//设置PB2引脚为复用功能模式 MODER[5:4]=10
//GPIOB->MODER &= (~(0x3 << 4));
GPIOB->MODER &= (~(0x1 << 4));
GPIOB->MODER |= (0x1 << 5);
//设置PB2引脚的复用功能 GPIOB_AFRL[11:8] = 1000
//GPIOB->AFRL &= (~(0x7 << 8));
GPIOB->AFRL &= (~(0xF << 8));
GPIOB->AFRL |= (0x1 << 11);
/*****************USART章节初始化*****************/
//0.设置串口不使能 UE: CR1[0] = 0
USART4->CR1 &= (~(0x1 << 0)); //error
//1.-设置1位起始位,8位数据位 M1,M0: CR1[28][12] = 00
USART4->CR1 &= (~(0x1 << 12));
USART4->CR1 &= (~(0x1 << 28));
//2.-无奇偶校验位 PCE: CR1[10] = 0
USART4->CR1 &= (~(0x1 << 10));
//3.-设置1位停止位 CR2[13][12] = 00
USART4->CR2 &= (~(0x3 << 12));
//4.-设置串口16倍采样率 OVER8: CR1[15] = 0
USART4->CR1 &= (~(0x1 << 15));
//5.-串口不分频 PRESC[3:0] = 0000
USART4->PRESC &= (~(0xF << 0));
//6.-设置串口波特率为115200 BRR = 0x22B
USART4->BRR = 0x22B;
//7.-设置串口发送器使能 TE: CR1[3] = 1 //err
USART4->CR1 |= (0x1 << 3);
//8.-设置串口接收器使能 RE: CR1[2] = 1
USART4->CR1 |= (0x1 << 2);
//9.-设置串口使能 UE: CR1[0] = 1
USART4->CR1 |= (0x1 << 0);
}
//发送一个字符
void hal_put_char(const char ch)
{
//1.判断发送数据寄存器的TXE(ISR[7])位是否为空
//读0:为满,继续等待,读1:为空
while(!(USART4->ISR & (0x1 << 7)));
//2.将发送的内容,赋值给发送数据寄存器
USART4->TDR = ch;
//3.判断一帧数据是否发送完成 TC(ISR[6])
//ISR[6] == 0:没有发送完成,继续等待 1:发送完成
while(!(USART4->ISR & (0x1 << 6)));
}
//发送一个字符串
void hal_put_string(char* str)
{
int i = 0;
//1.判断是否为字符串结束标识'\0'
while(str[i] != 0)
{
while(!(USART4->ISR & (0x1 << 7))); //为满则一直等待
//2.一个一个字符发送
hal_put_char(str[i]);
while(!(USART4->ISR & (0x1 << 6)));
i++;
}
}
//接收一个字符
char hal_get_char()
{
//1.判断接收数据寄存器是否接收到数据 ISR[5]
while(!(USART4->ISR & (0x1 << 5)));
//2.将接收数据寄存器的内容读取出来
return (char)(USART4->RDR);
}
//接收一个字符串
char* hal_get_string()
{
int i = 0;
static char buf[128];
while('\r' != (buf[i] = hal_get_char()))
{
i++;
}
buf[i] = 0;
return buf;
}
//接收单个字符并立即回显,在用户输入回车后,将本行数据再次进行输出
char hal_get_chars()
{
char ch = 0;
//需要在下一次调用函数时,仍能保留buf和i的数据,因此放入静态区
static int i = 0;
static char buf[128];
//1.判断接收数据寄存器是否接收到数据 ISR[5]
while(!(USART4->ISR & (0x1 << 5)));
//2.将接收数据寄存器的内容读取出来
ch = USART4->RDR;
//立即对输入的单个字符进行回显
hal_put_char(ch);
//3.记录ch到buf静态区中
buf[i] = ch;
//向后偏移buf的输入指针
i++;
//输入了回车,用户终止了本次输入,将已有字符串再输出一次
if('\r'==ch)
{
buf[i-1] = 0; //为字符串加上结尾'\0',顺便覆盖掉最后一个'\r',在下面统一输出
hal_put_char('\n'); //在secureCRT中输入的换行不会进行换行,而是被输入给了芯片
hal_put_string(buf);//将已有字符串输出一次
hal_put_string("\r\n");//统一输出'\r\n'
i = 0; //数据已经被输出,下次从头开始
}
return ch;
}
main.c
#include "uart4.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()
// {
// char ch;
// char str[] = " hello world";
// hal_uart_init();
// /*原始调试*/
// hal_put_string(str);
// //换到下一行的首字符进行输入
// hal_put_char('\n');
// hal_put_char('\r');
// while(1)
// {
// ch = hal_get_char();
// hal_put_char(ch+1);
// }
// return 0;
// }
//字符串回显代码
int main()
{
char ch = '6';
char str[] = " hello world";
hal_uart_init();
/*原始调试*/
hal_put_string(str);
hal_put_char(ch);
hal_put_char(ch);
hal_put_char(ch);
//换到下一行的首字符进行输入
hal_put_char('\n');
hal_put_char('\r');
while(1)
{
//循环接收字符并回显,在用户输入回车后,将本行数据再次进行输出
ch = hal_get_chars();
}
//没有回显的循环代码
// while(1)
// {
// buf = hal_get_string();
// //在secureCRT输入数据不会自动回显,回显需要单个字符回显
// hal_put_string(buf);
// hal_put_string(buf);
// }
return 0;
}
作业2结果
串口解析器(选作)
1.实验要求:串口输入相应的命令,控制对应的硬件进行工作
例如:在串口工具输入led1on----->板子led1点亮
在串口工具输入led1off----->板子led1熄灭
在串口工具输入led2on----->板子led2点亮
在串口工具输入led2off----->板子led2熄灭
在串口工具输入led3on----->板子led3点亮
在串口工具输入led3off----->板子led3熄灭