2022-2-21作业

作业:

1.实验串口收发一个字符

2.实验串口收发一个字符串

3.用swi指令验证异常处理流程(四大步三小步)


uart4.h:

#ifndef __UART4_H__
#define __UART4_H__

#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_uart.h"

//初始化串口
void hal_uart_init();

//发送一个字节
void uart_put_char(const char str);

//发送一个字符串
void uart_put_string(const char* str);

//接受一个字符
char uart_get_char();

//接收一个字符串
char* uart_get_string();

#endif

uart4.c:

#include "uart4.h"

extern void printf(const char *fmt, ...);

//初始化串口
void hal_uart_init()
{
	/*********RCC章节初始化********/
	RCC->MP_AHB4ENSETR |= (0x1 << 1);
	RCC->MP_AHB4ENSETR |= (0x1 << 6);
	RCC->MP_APB1ENSETR |= (0x1 << 16);
	/*********GPIO章节初始化*******/
	GPIOB->MODER &= (~(0x3 << 4)); 	//设置GPIO模式为复用模式
	GPIOB->MODER |= (0x1 << 5);
	GPIOB->AFRL &= (~(0xF << 8));
	GPIOB->AFRL |= (0x1 << 11);
	GPIOG->MODER &= (~(0x3 << 22)); //设置GPIO模式为复用模式
	GPIOG->MODER |= (0x1 << 23);
	GPIOG->AFRH &= (~(0xF << 12));
	GPIOG->AFRH |= (0x3 << 13);
	/*********UART章节初始化*******/
	USART4->CR1 &= (~(0x1 << 28)); 	//设置数据位宽度为8位
	USART4->CR1 &= (~(0x1 << 12));  
	USART4->CR1 &= (~(0x1 << 15)); 	//设置串口采样率
	USART4->CR1 &= (~(0x1 << 10)); 	//设置无奇偶校验位
	USART4->CR1 |= (0x1); 			//串口使能
	USART4->CR1 |= (0x1 << 2); 		//串口发送器使能
	USART4->CR1 |= (0x1 << 3); 		//串口接收器使能
	USART4->CR2 &= (~(0x3 << 12)); 	//设置串口1位停止位
	USART4->BRR = 0x22B; 		//设置串口波特率
}

//发送一个字节
void uart_put_char(const char str)
{
	//1.判断发送数据寄存器是否为空,为空才可以发送下一个字节
	//ISR[7]  
	//读0:发送数据寄存器满,需要等待
	//读1:发送数据寄存器空,才可以发送下一个字节数据
	while(!(USART4->ISR & (0x1 << 7)));

	//2.将要发送的字符写到发送数据寄存器中
	USART4->TDR = str;

	//3.判断发送数据是否完成 ISR[6]
	while(!(USART4->ISR & (0x1 << 6)));
	printf("\n");
}

//发送一个字符串
void uart_put_string(const char* str)
{
	//判断是否为'\0',一个字符一个字符发
	for(int i = 0; str[i] != '\0'; i++)
	{
		//1.判断发送数据寄存器是否为空,为空才可以发送下一个字节
		//ISR[7]  
		//读0:发送数据寄存器满,需要等待
		//读1:发送数据寄存器空,才可以发送下一个字节数据
		while(!(USART4->ISR & (0x1 << 7)));

		//2.将要发送的字符写到发送数据寄存器中
		USART4->TDR = str[i];

		//3.判断发送数据是否完成 ISR[6]
		while(!(USART4->ISR & (0x1 << 6)));
	}
	printf("\n");
}

//接受一个字符
char uart_get_char()
{
	char ch;
	//1.判断接收数据寄存器是否有数据可读 ISR[5]
	while(!(USART4->ISR & (0x1 << 5)));

	//2.将接收到的数据读出来
	ch = USART4->RDR;

	return ch;
}

char buff[50] = {0};
//接收一个字符串
char* uart_get_string()
{
	int i = 0;

	//for循环
	//当键盘的回车键'\r'按下之后,字符串输入完成
	for(i = 0; i < 47; i++)
	{
		buff[i] = uart_get_char();	
		if(buff[i] == '\r')
			break;
	}
	
	//字符串补'\0'
	buff[i] = '\0';
	printf("\n");

	return buff;
}

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()
{
	// 串口初始化
	hal_uart_init();
	// 实现串口数据收发
	uart_put_char('a');
	uart_put_string("hello world");
	while(1)
	{
		//uart_put_char(uart_get_char()+1);
		uart_put_string(uart_get_string());
	}
	return 0;
}

测试结果如下:

2022-2-21作业_第1张图片


 用swi指令验证异常处理流程(四大步三小步)

.text	@文本段
.globl _start	@声明一个_start全局函数

_start:	@_start标签入口
	
	@1.构建异常向量表
	@2.异常源--->标签
	b reset_handler			@reset处理程序
    b undef_handler			@未定义处理程序
    b swi_handler			@软中断处理程序
    b pref_abort_handler	@取指令中止
    b data_abort_handler	@取数据中止
    b no_use_handler		@未使用程序
    b irq_handler			@中断处理程序
    b fiq_handler			@快速中断处理程序

reset_handler:
	@3.系统一上电处于SVC模式
	@4.从SVC模式切换到USER模式
	msr CPSR, #0xD0
	
	@5.USER模式实现如下内容
		@1.初始化栈指针
		ldr sp,=0x40000800
		@2.分别对r0,r1寄存器赋值
		mov r0, #3
		mov r1, #4
		@3.执行软中断指令--->四大步三小步
		swi #1
		
stop:	@stop标签的入口,相当于C语言中的while(1)
	b stop
	
undef_handler:
swi_handler:
	@6.SVC模式下执行内容
	@ldr sp,=0x40000800
		@1.压栈保存现场
		stmfd sp!, {r0-r1,lr}
		@2.分别对r0,r1寄存器赋值
		mov r0, #1
		mov r1, #2
		@3.恢复现场
		ldmfd sp!, {r0-r1,r12}
		mrs r11, spsr
		msr cpsr, r11
		mov pc,r12
	
pref_abort_handler:
data_abort_handler:
no_use_handler:
irq_handler:
fiq_handler:
	
.end	@结束标志
	

你可能感兴趣的:(单片机,stm32,嵌入式硬件)