14. UART串口通信

news2024/9/30 1:37:19

14. UART串口通信

  • 1. UART
    • 1.1 UART 通信格式
    • 1.2 UART 电平标准
    • 1.3 I.MX6U UART 简介
      • 1.3.1 控制寄存器1 UARTx_UCR1(x=1~8)
      • 1.3.2 控制寄存器2 UARTx_UCR2
      • 1.3.3 控制寄存器3 UARTx_UCR3
      • 1.3.4 状态寄存器2 UARTx_USR2
      • 1.3.4 UARTx_UFCR 、 UARTx_UBIR 和 UARTx_UBMR
      • 1.3.5 UARTx_URXD 和 UARTx_UTXD
    • 1.4 代码实例
    • 1.5 编译下载
  • 2. 串口格式化函数
    • 2.1 代码实例
    • 2.2 编译下载

1. UART

1.1 UART 通信格式

串口通常也叫 COM 接口,串行接口指的是数据一个一个的顺序传输,通信线路简单。使用两条线就可以实现双向通信,一条用于发送,一条用于接口。UART 是异步串行收发器,与外界相连最少需要三条线:TXD发送、RXD接收和 GND地线。在这里插入图片描述
空闲位: 数据线在空闲状态的时候为逻辑1状态,也就是高电平,表示没有数据线空闲,没有数据传输。
起始位: 当要传输数据的时候先传输一个逻辑0,也就是将数据线拉低,表示开始数据传输
数据位: 数据位就是实际要传输的数据,可选择 5 ~ 8 位,一般都是按照字节传输数据的,一个字节 8 位,因此数据位通常是 8 位的,低位在前,先传输,高位最后传输。
奇偶检验位: 这是对数据中 1 的位数进行奇偶检验用的,可以不使用该功能
停止位: 数据传输完成标志位,停止位的位数可以选择 1、1.5 或 2 位高电平,一般都选择 1 位停止位
波特率: 就是 UART 数据传输的速率,也就是每秒传输的数据位数,一般选择 9600、19200、115200 等

1.2 UART 电平标准

UART 一般的接口电平有 TTL 和 RS-232。TTL 电平低电平表示逻辑 0,高电平表示逻辑 1;RS-232 采用差分线,-3 ~ -15 表示逻辑 1,3 ~ 15 表示逻辑 0.
在这里插入图片描述
上图所示就是 TTL 电平接口,下图是 RS-232电平接口
在这里插入图片描述
但是现在笔记本几乎没有这种接口,就有了usb转TTL芯片

1.3 I.MX6U UART 简介

一共有 8 个UART,主要特性如下:

  1. 兼容 TIA/EIA-232F标准,速度最高可达 5Mbit/s
  2. 支持串行 IR 接口,兼容 IrDA,最高可达115.2Kbit/s
  3. 支持 9 位或者多节点模式
  4. 1 或 2 位停止位
  5. 可编程的奇偶检验
  6. 自动波特率检查,最高支持 115.2 Kbit/s
    这里只用到最基本的串口功能。UART 的时钟源是由寄存器 CCM_CSCDR1 的 UART_CLK_SEL 位来选择的,当为 0 的时候 UART 的时钟源为 pll3_80m(80MHz),如果为 1 的时候 UART 的时钟源为 osc_clk(24M),一般选择 pll3_80m。寄存器 CCM_CSCDR1 的 UART_CLK_PODF 位是 UART 的时钟分频值,可设置 0 ~ 63,分别对应 1 ~ 64 分频,一般设置 1 分频,因此最终进入 UART 的时钟源是 80 MHz

1.3.1 控制寄存器1 UARTx_UCR1(x=1~8)

在这里插入图片描述
ADBR(bit14): 自动波特率检测使能位,为 0 的时候关闭自动波特率检测,为 1 的时候使能波特率检测
UARTEN(bit0): UART 使能位,为 0 的时候关闭 UART,为 1 的时候使能

1.3.2 控制寄存器2 UARTx_UCR2

在这里插入图片描述
IRTS(bit14): 为 0 的时候使用 RTS 引脚功能,为 1 的时候忽略 RTS 引脚
PREN(bit8): 奇偶校验使能位,为 0 的时候关闭奇偶检验,为 1 的时候使能
PROE(bit7): 奇偶检验模式选择位,开启奇偶检验以后此位如果为 0 就是用偶校验,为 1 就是用基校验
STOP(bit6): 停止位数量,为 0 的话 1 位停止位,为 1 的话 2 位停止位
WS(bit5): 数据位长度,为 0 的时候选择 7 位数据位,为 1 的时候选择 8 位数据位
TXEN(bit2): 发送使能位,0 关闭发送功能,1 打开发送功能
RXEN(bit1): 接收使能位,0 关闭接收功能,1 打开接收功能
SRST(bit0): 软件复位,0 的时候软件复位 UART,为 1 的时候表示复位完成,复位完成后此位会自动置 1,表示复位完成。此位只能写0,写1会被忽略

1.3.3 控制寄存器3 UARTx_UCR3

在这里插入图片描述
这里只用到了 RXDMUXSEL(bit2),这个位应该始终为1

1.3.4 状态寄存器2 UARTx_USR2

在这里插入图片描述
TXDC(bit3): 发送完成标志位,为 1 的时候表明发送缓冲(TxFIFO) 和移位寄存器为空,也就是发送完成,向 TxFIFO 写入数据此位就会自动清零
RDR(bit0): 数据接收标志位,为 1 的时候表明至少接收到一个数据,从寄存器 UARTx_URXD 读取接收到的数据以后此位会自动清零

1.3.4 UARTx_UFCR 、 UARTx_UBIR 和 UARTx_UBMR

UARTx_UFCR 用到的位是 RFDIV(bit9:7),用来设置参考时钟分频
在这里插入图片描述
通过这三个寄存器可设置波特率,公式如下:
在这里插入图片描述
Ref Freq:经过分频以后进入 UART 的最终时钟频率
UBMR:寄存器UBMR中的值
UBIR:寄存器UBIR中的值
如果要设置115200,那么设置 RFDIV 为 1 分频,Ref Freq=80MHz,UBIR=71,UBMX=3124

1.3.5 UARTx_URXD 和 UARTx_UTXD

这两个是接收和发送数据寄存器,低八位为接收到的和要发送的数据。

1.4 代码实例

bsp_uart.h

#pragma once
#include "imx6ul.h"

void uart_init();
void uart_io_init();
void uart_disable(UART_Type *base);
void uart_enable(UART_Type *base);
void uart_softreset(UART_Type *base);
void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz);
void putc(unsigned char c);
void puts(char *str);
unsigned char getc();
void raise(int sig_nr);

bsp_uart.c

#include "bsp_uart.h"

// 初始化串口1,波特率为115200
void uart_init()
{
	// 初始化串口 IO
	uart_io_init();

	// 初始化 UART1
	uart_disable(UART1);		// 先关闭UART1
	uart_softreset(UART1);		// 软件复位UART1
	UART1->UCR1=0;				// 先清除 UCR1 寄存器
	UART1->UCR1 &= ~(1<<14);	// 关闭自动波特率检测

	// 设置 UCR2 寄存器,忽略RTS引脚,关闭奇偶检验,设置1位停止位,8位数据位,打开发送和接收
	UART1->UCR2 |= (1<<14) | (1<<5) | (1<<2) | (1<<1);

	UART1->UCR3 |= 1<<2;

	// 设置波特率
	UART1->UFCR = 5<<7;
	UART1->UBIR = 71;
	UART->UBMR = 3124;

	// 使能串口
	uart_enable(UART1);
}

// 初始化串口1所使用的引脚
void uart_io_init()
{
	IOMUXC_SetPinMUX(IOMUXC_UART1_TX_DATA_UART1_TX, 0);
	IOMUXC_SetPinMUX(IOMUXC_UART1_RX_DATA_UART1_RX, 0);
	IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);
	IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
}

// 关闭指定的UART
void uart_disable(UART_Type *base)
{
	base->UCR1 &= ~(1<<0);
}	

// 打开指定的UART
void uart_enable(UART_Type *base)
{
	base->UCR1 |= (1<<0);	
}

// 复位指定的UART
void uart_softreset(UART_Type *base)
{
	base->UCR2 &= ~(1<<0);				// 复位
	while((base->UCR2 & 0x1) == 0);		// 等待复位完成,复位完成后此位自动置1
}

// 设置波特率,由官方 SDK 包移植过来
void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz);

// 发送一个字符
void putc(unsigned char c)
{
	while(((UART1->USR2 >>3) &0x01)==0);	// 等待上一次发送完成,发送完成会清零
	UART1->UTXD = c & 0xFF;					
}

// 发送一个字符串
void puts(char *str)
{
	char *p = str;
	while(*p)
	{
		putc(*p++);
	}
}

// 接收一个字符
unsigned char getc()
{
	while((UART1->USR2 & 0x1)==0);	// 等待接收完成
	return UART1->URXD;
}

// 防止编译器报错
void raise(int sig_nr)
{}

main.c

#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_uart.h"

int main()
{
	unsigned char a = 0;
	unsigned char state = OFF;
	int_init();
	imx6u_clkinit();
	delay_init();
	clk_enable();
	led_init();
	beep_init();
	uart_init();
	while(1)
	{
		puts("请输入一个字符:");
		a=getc();
		putc(a);	// 数据回显,就是将输入的数据显示出来,如果没有这一行,效果就像linux系统中输入密码什么都不显示一样
		puts("\r\n");
			
		puts("输入的字符为:");
		putc(a);
		puts("\r\n\r\n");

		state = !state;
		led_switch(LED0, state);
	}
	return 0;
}

1.5 编译下载

在通用makefile文件中,将 TARGET 修改为 uart,在 INCDIRS 和 SRCDIRS 中加入 bsp/uart。在设置波特率函数中使用到了除法运算,链接的时候需要将编译器的数学库也链接进来,并且使用 -L来指定库所在的目录。

LIBPATH := -lgcc -L /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4

-fno-builtin表示不使用内建函数,也就可以自己实现该函数,否则会发生冲突

$(SOBJS) : obj/%.o : %.S
	$(CC) -Wall -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<

2. 串口格式化函数

2.1 代码实例

其余函数基本不变,多添加一个stdio.h头文件

int main()
{
	int a, b;
	unsigned char state = OFF;
	int_init();
	imx6u_clkinit();
	delay_init();
	clk_enable();
	led_init();
	beep_init();
	uart_init();
	while(1)
	{
		printf("请输入两个整数:");
		scanf("%d%d, &a, &b);
		printf("\r\n数据%d + %d = %d\r\n\r\n",a,b,a+b);
		state = !state;
		led_switch(LED0, state);
	}
	return 0;
}

2.2 编译下载

修改 TARGET,在 INCDIRS 中添加stdio/include,在 SRCDIRS 中添加 stdio/lib。编译C文件时需要添加选项

$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1235229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA-运行测试方法提示Command line is too long

使用IDEA版本 执行时提示 处理方法&#xff1a; 1&#xff0c; 2&#xff0c;

electron项目开机自启动

一、效果展示&#xff1a;界面控制是否需要开机自启动 二、代码实现&#xff1a; 1、在渲染进程login.html中&#xff0c;画好界面&#xff0c;默认勾选&#xff1b; <div class"intro">开机自启动 <input type"checkbox" id"checkbox&quo…

MySQL数据库系统教程

基础篇 通用语法及分类 DDL: 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表、字段&#xff09;DML: 数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQL: 数据查询语言&#xff0c;用来查询数据库中表的记录DCL: 数据控制语言&#xff0c;用…

Window下如何对Redis进行开启与关闭

目录 前言1. 图文界面2. 命令行 前言 由于长期使用Linux界面&#xff0c;对于Window下的Redis&#xff0c;不知如何下手。特此记录该博文 特别注意&#xff0c;刚下载好的Redis&#xff0c;如果需要配置密码&#xff0c;可以再该文件进行配置&#xff1a;redis.windows-servi…

Vue框架学习笔记——v-bind数据单向绑定和v-model数据双向绑定

文章目录 v-bind&#xff0c;数据单向绑定简写形态&#xff08;省略v-bind&#xff0c;只留冒号&#xff09;示例一&#xff08;将输入框数据改为&#xff1a;哈哈哈哈哈&#xff09;&#xff1a;实例二&#xff08;将Vue实例中的name改为字符串&#xff1a;"单向绑定&quo…

达索系统3DEXPERIENCE WORKS 2024 Fabrication新功能

当发现产品的制造环节&#xff0c;以及因产品模型本身的设计而导致制造环节存在不合理性&#xff0c;从而导致加工制造成本增加。 快速判断&#xff0c;轻松协作 在达索系统3DEXPERIENCE WORKS 2024中我们可以快速的判断产品的可制造性&#xff0c;以及快速与前端设计沟通协作…

怎么让NetCore接口支持Json参数

项目&#xff1a;NetCore Web API 接口支持Json参数需要安装Newtonsoft.Json.Linq和Microsoft.AspNetCore.Mvc.NewtonsoftJson Program代码 //支持json需要安装Microsoft.AspNetCore.Mvc.NewtonsoftJson using Newtonsoft.Json.Serialization;var builder WebApplication.Cr…

【狂神说Java】redis

✅作者简介&#xff1a;CSDN内容合伙人、信息安全专业在校大学生&#x1f3c6; &#x1f525;系列专栏 &#xff1a;【狂神说Java】 &#x1f4c3;新人博主 &#xff1a;欢迎点赞收藏关注&#xff0c;会回访&#xff01; &#x1f4ac;舞台再大&#xff0c;你不上台&#xff0c…

SpringBoot 自动装配原理 - 支付宝支付封装starter

SpringBoot 自动装配 SpringBoot 自动装配原理详细介绍自定义 Spring Boot Starter1.读取配置文件2.注册 AlipayClient bean3.核心代码编写4.注册 AlipayAPI bean5.编写 META-INF/spring.factories 文件6.项目结构测试1.创建一个测试项目&#xff0c;引入自定义 starter 依赖2.…

解锁潜力:创建支持Actions接口调用的高级GPTs

如何创建带有Actions接口调用的GPTs 在本篇博客中&#xff0c;我们将介绍如何创建一个带有Actions接口调用的GPTs &#xff0c;以及如何进行配置和使用。我们将以 https://chat.openai.com/g/g-GMrQhe7ka-gptssearch 为例&#xff0c;演示整个过程。 Ps: 数据来源&#xff1a…

如何在3dMax中使用Python返回场景内所有对象的列表?

如何在3dMax中使用Python返回场景内所有对象的列表&#xff1f; 3dMax支持开发基于Python的工具和扩展&#xff0c;因此可以对其进行自定义并将其集成到现代数字内容创建管道中。为此&#xff0c;3dMax集成了Python 3.9解释器&#xff0c;并通过pymxs API公开了3dMax的丰富功能…

2023年山东省安全员B证证模拟考试题库及山东省安全员B证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年山东省安全员B证证模拟考试题库及山东省安全员B证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;山东省安全员B证证模拟考试题库是根据山东省安全员B证最新版教材&#xff0c;山东省安全员B证大纲整理…

金融企业为啥不选择云服务器还是考虑服务器托管

尽管云主机在近年来的发展中取得了巨大的成功&#xff0c;但在金融行业中&#xff0c;一些客户仍然倾向于将服务器托管到数据中心&#xff0c;而不是使用云主机。以下是一些金融客户选择将服务器托管到数据中心的原因&#xff1a; 数据安全性&#xff1a;金融行业对数据的安全性…

中国毫米波雷达产业分析1——毫米波雷达行业概述

一、毫米波雷达简介 &#xff08;一&#xff09;产品定义 雷达是英文Radar的音译&#xff0c;源于Radio Detection and Ranging的缩写&#xff0c;原意是“无线电探测和测距”&#xff0c;即用无线电方法发现目标并测定它们在空间的位置。毫米波雷达是指一种工作在毫米波频段的…

hook io异常注入

文中code https://gitee.com/bbjg001/darcy_common/tree/master/io_hook 需求引入 最近工作需要&#xff0c;需要验证一下我们的服务在硬盘故障下的鲁棒性。 从同事大佬哪里了解到hook技术&#xff0c;可以通过LD_PRELOAD这个环境变量拦截依赖库的调用链&#xff0c;将对标准…

从0开始学习JavaScript--JavaScript中的对象

JavaScript中的对象是一种重要的数据结构&#xff0c;它不仅是语言的基石&#xff0c;还提供了丰富的功能和灵活性。本文将深入研究JavaScript对象的创建、属性访问、方法定义&#xff0c;以及实际应用中的技巧&#xff0c;通过丰富的示例代码&#xff0c;帮助读者更全面地了解…

pycharm统计代码运行时间

方法1&#xff1a;写代码实现 import……&#xff08;自己会用到的包&#xff09; import time start time.perf_counter() #开始计时#代码开始了 …… …… …… end time.perf_counter() #结束计时 runtime end - start print(f"输出代码运行时间{runtime}")…

七天.NET 8操作SQLite入门到实战 - 第二天 在 Windows 上配置 SQLite环境

前言 SQLite的一个重要的特性是零配置的、无需服务器&#xff0c;这意味着不需要复杂的安装或管理。它跟微软的Access差不多&#xff0c;只是一个.db格式的文件。但是与Access不同的是&#xff0c;它不需要安装任何软件&#xff0c;非常轻巧。 七天.NET 8操作SQLite入门到实战…

RabbitMQ消息队列快速入门

RabbitMQ消息队列快速入门 初始MQ MQ全称为Message Queue&#xff0c;即消息队列&#xff0c;是在消息的传输过程中保存消息的容器。它是典型的生产者-消费者模型。 生产者不断向消息队列中生产消息&#xff0c;消费者不断的从队列中获取消息。消息的生产和消费都是异步的&am…

多项式求和

题目描述 给定程序中 fun 函数的功能是&#xff1a;求出以下分数序列的前 n 项之和&#xff0c;并通过函数值返回 main 函数。 输入格式 输入参数。 输出格式 计算公式返回的结果。 输入输出样例 输入1 5 输出1 8.391667 python解&#xff1a; def fun(n):a1b2s0for…