头文件部分
#ifndef __UART4_H__
#define __UART4_H__
#include "stm32mp1xx_uart.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#define LEN 50
// 初始化的函数
void uart4_init();
// 发送一个字节的函数
void send_char(const char ch);
// 发送字符串的函数
void send_string(const char *str);
// 接收一个字符的函数
char recv_char();
// 接收一个字符串的函数
char * recv_string(char str[]);
#endif // __UART4_H__
功能函数部分
#include "uart4.h"
extern void delay_ms(unsigned int ms);
// 初始化的函数
void uart4_init()
{
// 1. 使能GPIOB,GPIOG外设的时钟 RCC_MP_AHB4ENSETR[1][6] = 0b1
RCC->MP_AHB4ENSETR = (0x1 << 1) | (0x1 << 6);
// 2. 设置PB2, 和 PG11引脚为复用的功能
// GPIOB_MODER[5:4] = 0b10 GPIOG_MODER[23:22] = 0b10
GPIOB->MODER &= (~(0x3 << 4));
GPIOB->MODER |= (0x2 << 4);
GPIOG->MODER &= (~(0x3 << 22));
GPIOG->MODER |= (0x2 << 22);
// 3. 设置PB2引脚为UART4_RX功能 GPIOB_AFRL[11:8] --> AF8 --> 0b1000
// 设置PG11引脚为UART4_TX功能 GPIOG_AFRH[15:12] --> AF6 --> 0b0110
GPIOB->AFRL &= (~(0xF << 8));
GPIOB->AFRL |= (0x8 << 8);
GPIOG->AFRH &= (~(0xF << 12));
GPIOG->AFRH |= (0x6 << 12);
// 4. 使能UART4外设的时钟 RCC_MP_APB1ENSETR[16] = 0b1
RCC->MP_APB1ENSETR = (0x1 << 16);
// 5. 判断UART4串口是否使能,如果使能则禁止串口
if (USART4->CR1 & (0x1 << 0)) {
delay_ms(2000); // 等待之前的串口的数据发送完成之后在禁止串口
USART4->CR1 &= (~(0x1 << 0)); // 禁止串口的使能
}
// 6. 设置数据位为8位的数据宽度 USART4_CR1[28][12] = 0b00
USART4->CR1 &= ~((0x1 << 12) | (0x1 << 28));
// 7. 禁止校验位,不使用校验 USART4_CR1[10] = 0b0
USART4->CR1 &= (~(0x1 << 10));
// 8. 设置串口的采样率为16倍或者8倍,最终会影响波特率的计算 USART4_CR1[15]
USART4->CR1 &= (~(0x1 << 15));
// 9. 设置停止位的个数为1位 USART4_CR2[13:12] = 0b00
USART4->CR2 &= (~(0x3 << 12));
// 10. 设置串口时钟的分频寄存器 USART4_PRERC[3:0] 最终也会影响波特率的计算
// usart_ker_ck 时钟源的频率等于 64MHz
// usart_ker_ck_pesc = usart_ker_ck / USART4_PRESC[3:0]
USART4->PRESC &= (~(0xF << 0));
// 11. 设置串口的波特率为115200bps USART4_BRR[15:0]
USART4->BRR = 0x22B;
// 12. 使能串口发送器 USART4_CR1[3] = 0x1
USART4->CR1 |= (0x1 << 3);
// 13. 使能串口接收器 USART4_CR1[2] = 0x1
USART4->CR1 |= (0x1 << 2);
// 14. 使能串口 USART4_CR1[0] = 0x1
USART4->CR1 |= (0x1 << 0);
}
// 发送一个字节的函数
void send_char(const char ch)
{
// 1. 判断发送寄存器是否为空,如果为空发送下一个字节的数据,
// 如果不为空等待发送数据寄存器为空。 USART4_ISR[7]
while(!(USART4->ISR & (0x1 << 7)));
// 2. 发送数据,向发送数据寄存器中写入数据 USART4_TDR[7:0]
USART4->TDR = ch;
if (ch == '\n')
send_char('\r');
}
// 发送字符串的函数
void send_string(const char *str)
{
// 1. 调用发送字符的函数一个一个的发送,字符串的结尾为‘/0’
while (*str != '\0') {
send_char(*str);
str++;
}
}
// 接收一个字符的函数
char recv_char()
{
char ch;
// 1. 判断接收数据寄存器中是否有有效的数据,如果有数据则读取数据
// 如果没有有效的数据,则等待有有效的数据之后在读取。 USART4_ISR[5]
while(!(USART4->ISR & (0x1 << 5)));
// 2. 从接收数据寄存器中读取数据到ch变量中 USART4_RDR[7:0]
ch = (char)USART4->RDR;
return ch;
}
// 接收一个字符串的函数
char buffer[LEN] = {0};
char * recv_string(char str[])
{
// 1 一个字符一个字符的接收,接收到之后将数据存到buffer缓冲区中,
// 最多接收49,接收结束之后结尾需要补'\0'.
// 接收的情况,一种是接收49个字符结束,另一种是按下enter键之后结束
// enter键是一个字符'\r'.
unsigned int i;
for (i = 0; i < LEN -1 ;i++) {
// 接收一个字符
buffer[i] = recv_char();
// 在串口工具上回显接收到的字符
send_char(buffer[i]);
if (buffer[i] == '\r') // 按下enter键结束字符串的接收
break;
}
buffer[i] = '\0'; // 字符串的结尾补0
send_char('\n');
return buffer;
}
主函数部分
#include "uart4.h"
void delay_ms(unsigned int ms)
{
int i,j;
for(i = 0; i < ms;i++)
for (j = 0; j < 1800; j++);
}
extern char buffer[LEN];
int main()
{
char *str;
uart4_init(); // 串口的初始化
while(1)
{
// 接收一个字符串
str = recv_string(buffer);
send_string(str);
send_char('\n');
}
return 0;
}