7.1 ARM cortex-A7 UART4

cpp 复制代码
#include "include/uart4.h"

void delay_ms(int ms) {
	for (int i = 0; i < ms; i++)
		for (int j = 0; j < 1000; j++);
}



int main() {
	hal_uart4_init();
	while (1)
		hal_string_put(hal_string_get());
	return 0;
}
cpp 复制代码
#ifndef __UART4_H__
#define __UART4_H__

#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
#define GET_BYTE(x, byte) (x & (0xFF << (8 * byte)) >> (8 * byte))


// RCC / GPIO / UART4 初始化
void hal_uart4_init();
// 发送一个字符
void hal_char_put(const char ch);
// 发送一个字符串
void hal_string_put(const char* str);
// 接收一个字符
char hal_char_get();
// 接收一个字符串
char* hal_string_get();


#endif
cpp 复制代码
#include "../include/uart4.h"
#include "../include/stm32mp1xx_gpio.h"
#include "../include/stm32mp1xx_rcc.h"
#include "../include/stm32mp1xx_uart.h"
// UART4_RX => PB2
// UART4_TX => PG11

extern void delay_ms(int ms);

/**
 * @brief RCC && GPIO && UART4 初始化
 *
 */
void hal_uart4_init() {
	/*********** RCC初始化 ***********/
	// 1. 使能GPIOB、G组时钟 RCC_MP_AHB4ENSETR[6,1] = 1
	RCC->MP_AHB4ENSETR |= 0x21 << 1;
	// 2. 使能UART4组时钟 RCC_MP_APB1ENSETR[16] = 1
	RCC->MP_APB1ENSETR |= 0x1 << 16;

	/*********** GPIO初始化 ***********/
	// 1. 设置PG11为复用功能模式
	GPIOG->MODER &= ~(0x3 << 22);
	GPIOG->MODER |= 0x2 << 22;
	// 2. 设置PB2为复用功能模式
	GPIOB->MODER &= ~(0x3 << 4);
	GPIOB->MODER |= 0x2 << 4;
	// 3. 设置PG11的复用功能为UART4_TX
	GPIOG->AFRH &= ~(0xF << 12);
	GPIOG->AFRH |= 0x6 << 12;
	// 4. 设置PB2的复用功能为UART4_RX
	GPIOB->AFRL &= ~(0xF << 8);
	GPIOB->AFRL |= 0x8 << 8;

	/*********** UART4初始化 ***********/
	// 1. 使UE、RE、TE失能,以便于初始化:
	if (USART4->CR1 & 0x1) {
		delay_ms(500);
		USART4->CR1 &= ~(0x1);
	}
	// 2. CR1寄存器的M、OVER8、PCE;
	// 1) M[1:0] = 00,1位起始位,8位数据位
	USART4->CR1 &= ~(0x1 << 28);
	USART4->CR1 &= ~(0x1 << 12);
	// 2) OVER8 = 0,16倍超采样
	USART4->CR1 &= ~(0x1 << 15);
	// 3) PCE = 0,无校验位
	USART4->CR1 &= ~(0x1 << 10);

	// 2. BRR寄存器的BRR;
	  // 1) BRR[15:0] = 0x160A,串口波特率115200Bps
	USART4->BRR &= ~(0xFFFF);
	USART4->BRR |= 0x22B;

	// 3. CR2寄存器的STOP;
	// 1) STOP[1:0] = 00,1位停止位
	USART4->CR2 &= ~(0x3 << 12);

	// 4. PRESC寄存器的PRESCALER;
	// 1) PRESCALER[3:0] = 0000,不分频
	USART4->PRESC &= ~(0xF);

	// 5. 使能UE、TE、RE开启串口收发
	USART4->CR1 |= 0xD;
}

/**
 * @brief 发送一个字符
 *
 * @param ch
 */
void hal_char_put(const char ch) {
	while (!GET_BIT(USART4->ISR, 7));
	USART4->TDR = ch;
	while (!GET_BIT(USART4->ISR, 6));
}

/**
 * @brief 发送一个字符串
 *
 * @param str
 */
void hal_string_put(const char* str) {
	while (*str)
		hal_char_put(*str++);
	hal_char_put('\r');
	hal_char_put('\n');
}

/**
 * @brief 接收一个字符
 *
 * @return char
 */
char hal_char_get() {
	while (!GET_BIT(USART4->ISR, 5));
	return USART4->RDR;
}

/**
 * @brief 接收一个字符串
 *
 * @return char*
 */
char* hal_string_get() {
	static char buf[128];
	for (int i = 0; i < sizeof(buf); i++)
		buf[i] = 0;
	int i;
	for (i = 0; i < 126; i++) {
		buf[i] = hal_char_get();
		hal_char_put(buf[i]);
		if (buf[i] == '\b') {
			hal_char_put(' ');
			hal_char_put('\b');
			buf[i--] = '\0';
			buf[i--] = '\0';
		}
		else if (buf[i] == '\r')
			break;
	}
	buf[i] = '\0';
	hal_char_put('\n');
	return buf;
}
相关推荐
AI+程序员在路上13 分钟前
Nand Flash与EMMC区别及ARM开发板中的应用对比
arm开发
17(无规则自律)6 小时前
深入浅出 Linux 内核模块,写一个内核版的 Hello World
linux·arm开发·嵌入式硬件
梁洪飞19 小时前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
代码游侠1 天前
学习笔记——Linux字符设备驱动
linux·运维·arm开发·嵌入式硬件·学习·架构
syseptember2 天前
Linux网络基础
linux·网络·arm开发
代码游侠2 天前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
程序猿阿伟2 天前
《Apple Silicon与Windows on ARM:引擎原生构建与模拟层底层运作深度解析》
arm开发·windows
wkm9562 天前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt
unicrom_深圳市由你创科技2 天前
基于ARM+DSP+FPGA异构计算架构的高速ADC采集卡定制方案
arm开发·fpga开发
松涛和鸣2 天前
DAY69 Practical Guide to Linux Character Device Drivers
linux·服务器·arm开发·数据库·单片机·嵌入式硬件