实验三 UART串口实验

1、总线相关的概念

总线:连接多个部件的信息传输线,是各部件共享的传输介质。

芯片内部总线:ARM内核和各种外设控制器连接的总线,比如AHB1 ~ AHB4, APB1 ~ APB4
		芯片内部总线又可以划分为地址总线和数据总线。

芯片外部总线:处理器和外设之间连接的总线,比如:串口,IIC, SPI,USB, 485, CAN

2、串行通信和并行通信的区别

串行通信:指的是同一时刻只能收或发一个bit位信息,因此只用1根信号线即可。 

并行通信:指的是同一时刻可以收或发多个bit位的信息,因此需要多根信号线才行。

image-20230718091543665

3、单工、半双工、全双工

单工:要么收,要么发,只能做接收设备或者发送设备。

半双工:可以收,可以发,但是不能同时收发。
		比如:IIC, 485, CAN, USB2.0
全双工:可以在同一时刻既接收,又发送。
		比如:UART, SPI, USB3.0

image-20230718092145895

4、同步通信和异步通信

同步通信: 
	一般情况下同步通信指的是通信双方根据同步时钟信号进行通信的方式。
	比如通信双方有一个共同的时钟信号,大家根据时钟信号的变化进行通信。
	一个时钟周期内,收发1个bit位的数据。
	   __    __    __    __
	__|  |__|  |__|  |__|  |__
	  \     /
	   \   /
	    1个时钟周期

同步通信总线:IIC, SPI

image-20230718092653463

异步通信:
	是指数据传输速度匹配依赖于通信双方有自己独立的系统时钟,
	大家约定好通信的速度。异步通信不需要同步信号,但是并不是说通信的过程不同步。
	一个时钟周期收发一个bit位的数据。
	
异步通信:UART,485,CAN,USB

image-20230718092941629

5、串口相关硬件的介绍

串口接口实物图及串口引脚的功能说明:

image-20230718093354231

image-20230718093456808

在实际开发中,串口常用的硬件连接:

串口常用的硬件连接主要使用3根线:RXD, TXD, GND
	RXD : 接收数据线
	TXD : 发送数据线
	GND : 共地

image-20230718093858010

6、在实际开发中串口常用的连接方式

	在实际开发中串口使用的范围非常的广泛,
	1> 可以用于通过串口打印调试信息到PC端的串口工具中;
	2> 可以使用串口实现两个设备间的通信,

串口常用连接方式1:

image-20230718095029740

image-20230718095039490

串口常用连接方式2:

image-20230718100820079

串口常用连接方式3:

image-20230718101206101

7、UART串口总线的通信协议

串口:异步串行全双工总线

image-20230718103624773

image-20230718103654854

串口常用的通信的协议:8N1
	8 : 8位数据位
	N : 没有校验位
	1 : 1个停止位

波特率:串口的传输的速率,每秒传输数据的bit位数,单位bps
	常用的串口的波特率:115200bps , 9600bps

image-20230718104024868

实验3 - UART串口实验

1、分析串口的电路图

image-20230718111350446

image-20230718111411720

image-20230718111426331

2、分析芯片手册

image-20230718112633910

2.1 分析2.5.2章节,确定GPIOB,GPIOG,UART4,RCC分别接到哪根总线上,以及外设控制器对应的寄存器的基地址

image-20230718113141769

image-20230718113236800

2.2 分析RCC章节,使能GPIOB,GPIOG,UART4外设控制器的时钟源

image-20230718113411906

image-20230718113424592

image-20230718113434883

image-20230718113541699

image-20230718113606100

2.3 分析GPIO章节,设置PB2和PG11引脚为串口的复用功能

image-20230718114054035

2.3.1 GPIOx_MODER寄存器

image-20230718114456119

2.3.2 GPIOx_AFRL寄存器

image-20230718114724199

image-20230718115016575

image-20230718115115967

image-20230718115107682

2.3.3 GPIOx_AFRH寄存器

image-20230718114756298

image-20230718115256448

image-20230718115225909

2.4 分析UART章节,设置串口的协议,串口的波特率,实现串口数据的收发

image-20230718134235384

image-20230718134340228

image-20230718134519699

image-20230718135205118

image-20230718135419879

2.4.1 USART_CR1寄存器 ---> 串口控制寄存器1

image-20230718135856305

image-20230718140025733

image-20230718140102123

image-20230718140155319

image-20230718140523731

image-20230605152245334

image-20230718140920201

image-20230718140944352

image-20230718141013791

image-20230718141032323

image-20230718141051753

2.4.2 USART_CR2寄存器 ---> 控制寄存器2

image-20230718141200011

image-20230718141229508

2.4.3 USART_BRR寄存器 ---> 串口波特率寄存器

image-20230718143455749


BRR[15:4] = USARTDIV[15:4]

当over8 = 0; 16倍的采样率,
	BRR[3:0] = USARTDIV[3:0]
	
当over8 = 1; 8倍的采样率
	BRR[2:0] = USARTDIV[3:0] >> 1
	BRR[3]必须保持清0的状态

image-20230718143841447

image-20230718144010054

假设usart_ker_ck_pres = 64MHz, 波特率为115200bps

则当采样率为16倍时,USARTDIV = 64 000 000 / 115200 = 555 = 0x22B
	BRR = 0x22B
	
当采样率为8倍时,USARTDIV = 2 * 64 000 000 / 115200 = 1111 = 0x457
	BRR = 0x453
	

2.4.4 USART_ISR寄存器 ----> 中断和状态寄存器

image-20230718144708944

image-20230718144956864

TXE[7] : 发送数据寄存器是否为空的标志位
	读0:表示发送数据寄存器不为空,不可以向发送数据寄存器中写入下一个字节数据
	读1:表示发送数据寄存器为空,可以向发送数据寄存器中写入下一个字节的数据

当发送数据寄存器中的数据被传送到发送移位寄存器时,硬件自动将TXE位置1.
当向发送数据寄存器中写入数据时,硬件自动将TXE位清0.

image-20230718145335043

RXNE[5] : 读接收数据寄存器非空的标志位
	读0:数据没有接收,不可以从接收数据寄存器中读取数据
	读1:接收数据寄存器有数据,可以从接收数据寄存器中读取数据

当接收数据移位寄存器中的数据被传送到接收寄存器时,硬件自动将RXNE位置1,
当从接收数据寄存器中读取数据之后,硬件自动将RXNE位清0.
	

2.4.5 USART_RDR寄存器 ----> 接收数据寄存器

image-20230718145752978

2.4.6 USART_TDR寄存器 ----> 发送数据寄存器

image-20230718145817186

2.4.7 USART_PRESC寄存器 ----> 串口分频寄存器

image-20230718145840332

3、编写串口的驱动代码

1. 串口的初始化
2. 发送一个字符的函数
3. 发送一个字符串的函数
4. 接收一个字符的函数
5. 接收一个字符串的函数

uart4.h

完成函数的声明

#ifndef _UART4_H_
#define _UART4_H_

#include "gpio.h"







void hal_uart_init();
void hal_sendchar(char data);
char hal_recvchar();
void hal_sendstring(char *data);
char *hal_recvstring();


#endif /*_UART4_H_*/

uart4.c 

注:串口中只有USART4提供给用户用于数据收发的功能,所以无需像LED和KEY一样封装一个库,不同的外设多次调用库函数,这个函数封装好后就只会在mian.c里调用,所以直接操作寄存器,只封装一个hal库即可。

#include "../include/uart4.h"
#include "../common/include/stm32mp1xx_uart.h"

extern void delay_ms(unsigned int ms);
void hal_uart_init(){
    //使能时钟
    RCC->MP_AHB4ENSETR |=(1<<1);
    RCC->MP_AHB4ENSETR |=(1<<6);
    RCC->MP_APB1ENSETR |=(1<<16);

    //GPIO
    GPIOB->MODER &=~(0b11<<4);
    GPIOB->MODER |=(0b10<<4);
    GPIOG->MODER &=~(0b11<<22);
    GPIOG->MODER |=(0b10<<22);


    GPIOB->AFRL &=~(0b1111<<8);
    GPIOB->AFRL |=(0b1000<<8);
    GPIOG->AFRH &=~(0b1111<<12);
    GPIOG->AFRH |=(0b0110<<12);
    
    

    //UART
    if(USART4->CR1 & 1){
        delay_ms(2000);
        USART4->CR1&=~1;//关闭串口
    } 
    //数据位  0b00
    USART4->CR1 &=~(1<<28);
    USART4->CR1 &=~(1<<12);
    //采样率   16倍
    USART4->CR1 &=~(1<<15);
    //校验位  无校验位
    USART4->CR1 &=~(1<<10);
    //停止位  1个
    USART4->CR2 &=~(0b11<<12);
    //波特率115200
    USART4->BRR=0x22B;
    //分频
    USART4->PRESC &=~(0b1111);
    //使能TE RE
    USART4->CR1 &=~(0b11<<2);
    USART4->CR1 |=(0b11<<2);
    //使能串口
    USART4->CR1 |=(1);
}
void hal_sendchar(const char data){
    while (!(USART4->ISR &(1<<7)));
    USART4->TDR=data;
    if(data=='\n'){//此时\n已经发给串口调试助手,光标已经在下一行,但是不在行首
        hal_sendchar('\r');
    }
}
char hal_recvchar(){
    char data;
    while(!(USART4->ISR &(1<<5)));
    data=(char)USART4->RDR;
    return data;
}


void hal_sendstring(const char *data){
    while(*data !='\0'){
        hal_sendchar(*data);
        data++;
    }
    
}
char buff[50]={0};
#if 1
char *hal_recvstring(){
    int i=0;
    for(;i<49;i++){
        buff[i]=hal_recvchar();
        hal_sendchar(buff[i]);
        if (buff[i] == '\r')//代表串口调试助手的enter,串口调试助手没有\0
        {
            break;
        }
    }
    buff[i]='\0';
    hal_sendchar('\n');
    return buff;
}
#endif

main.c

#include "include/led.h"
#include "include/key.h"
#include "include/uart4.h"
void delay_ms(unsigned int ms){
        int i, j;
        for (i = 0; i < ms; i++)
            for (j = 0; j < 1800; j++)
                ;
    }
int my_strcmp(const char* src,const char *dst){
        int ret = 0;
    while( !(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
    {
        src ++;
        dst ++;
    }
    if( ret < 0) ret = -1;
    else if(ret > 0) ret = 1;
    return ret;
}
int main(){
    led_init();
    hal_uart_init();



    //char data;
    char *str;
    while (1){
        #if 0
        data=hal_recvchar();
        hal_sendchar(data+1);
        #endif
        #if 0
        str=hal_recvstring();
        hal_sendstring(str);
        #endif
        #if 1
        //发送命令点灯
        
        str=hal_recvstring();
        if(my_strcmp(str,"led1on")==0){
            led_open_off(LED1,led_on);
        }else if(my_strcmp(str,"led2on")==0){
            led_open_off(LED2,led_on);
        }else if(my_strcmp(str,"led3on")==0){
            led_open_off(LED3,led_on);
        }else if(my_strcmp(str,"led1off")==0){
            led_open_off(LED1,led_off);
        }else if(my_strcmp(str,"led2off")==0){
            led_open_off(LED2,led_off);
        }else if(my_strcmp(str,"led3off")==0){
            led_open_off(LED3,led_off);
        }
        #endif
    }
        
}

4、编译,下载,调试

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UART(Universal Asynchronous Receiver/Transmitter)是一种通用异步收发器,可以将并行数据转换成串行数据,或将串行数据转换成并行数据。在串口通信中,UART通常用于将数据从微控制器或计算机发送到外设(如传感器、执行器等)或从外设接收数据并发送到微控制器或计算机。下面介绍UART串口通信实验原理。 UART串口通信实验步骤如下: 1. 确定串口通信参数:通信波特率、数据位数、停止位数、校验位等。波特率是串口通信中的重要参数,表示数据传输的速率,通常选择常见的波特率(如9600、115200等)。 2. 连接串口通信的设备:将微控制器或计算机的串口与外设的串口连接,使用串口线连接即可。需要注意的是,串口线的连接方式必须与设备的串口通信参数相匹配。 3. 编写程序:使用编程语言(如C语言)编写程序,实现数据的发送和接收。在程序中,需要设置串口通信参数,并使用串口发送和接收函数进行数据的传输。发送数据时,将数据转换为串行数据,并通过UART发送到外设;接收数据时,通过UART接收串行数据,并将其转换为并行数据,保存在缓冲区中。 4. 调试程序:将程序下载到微控制器或计算机中,通过串口进行调试。在调试过程中,可以使用示波器或串口调试软件查看串口发送和接收的数据,检查程序是否正常运行。 需要注意的是,串口通信中,外设和微控制器或计算机的串口通信参数必须相同才能正常进行通信。同时,在数据的发送和接收过程中,需要注意数据的格式和传输顺序,以免出现数据丢失或错误的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值