ARM_USART_串口通信

实验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熄灭

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值