串口这个东西很重要,罗里吧嗦的就不说了
参考资料:IMX6U参考手册,正点原子嵌入式linux驱动开发指南

1.UART简介

UART作为串口的一种,工作原理就是数据一位一位的进行传输,发送和接收各用一条线,因为UART接口与外界相连最少需要三个线:TXD、RXD、GND。UART的通信格式如下:

空闲位: 数据线在空闲状态的时候为逻辑"1"状态,表示没有数据线空闲,没有数据传输。
起始位: 当要传输数据的时候先传输一个逻辑0,也就是将数据线拉低,表示开始数据传输。
数据位: 数据位就是实际要传输的数据,数据位数可选择5~8,一般按照字节传输数据,一个字节 8 位,因此数据位通常是 8 位的。低位在前,先传输,高位最后传输。
奇偶校验位: 这是对数据中“1”的位数进行奇偶校验用的,可以不使用奇偶校验功能。
停止位: 数据传输完成标志位,停止位的位数可以选择 1 位、 1.5 位或 2 位高电平,一般都
选择 1 位停止位。

I.MX6U 一共有 8 个 UART,其主要特性如下:
①、兼容 TIA/EIA-232F 标准,速度最高可到 5Mbit/S。
②、支持串行 IR 接口,兼容 IrDA,最高可到 115.2Kbit/s。
③、支持 9 位或者多节点模式(RS-485)。
④、 1 或 2 位停止位。
⑥、可编程的奇偶校验(奇校验和偶校验)。
⑦、自动波特率检测(最高支持 115.2Kbit/S)。

UART的时钟源是由寄存器CCM_CSCDR1的UART_CLK_SEL位确定的,当为0的时候UART的时钟源为pll3_80m(80MHz),如果为 1 的时候 UART 的时钟源为 osc_clk(24M),一般选择 pll3_80m 作为 UART 的时钟源。寄存器 CCM_CSCDR1 的 UART_CLK_PODF(bit5:0)位是 UART 的时钟分频值,可设置 0~63,分别对应 1~64 分频,一般设置为 1 分频,因此最终进入 UART 的时钟为 80MHz

2.和UART相关的寄存器

  • UARTx_UCR1(x=1~8)
  • UARTx_UCR2
  • UARTx_UCR3
  • UARTx_USR2
  • UARTx_UFCR
  • UARTx_UBIR
  • UARTx_UBMR
  • UARTx_URXD
  • UARTx_UTXD

UARTx_UCR1


寄存器 UARTx_UCR1 我们用到的重要位如下:
**ADBR(bit14):**自动波特率检测使能位,为 0 的时候关闭自动波特率检测,为 1 的时候使
能自动波特率检测。
** UARTEN(bit0): ** UART 使能位,为 0 的时候关闭 UART,为 1 的时候使能 UART

UARTx_UCR2


寄存器 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 的时候关闭 UART 的发送功能,为 1 的时候打开 UART的发送功能。
RXEN(bit1): 接收使能位,为 0 的时候关闭 UART 的接收功能,为 1 的时候打开 UART的接收功能。
SRST(bit0): 软件复位,为 0 的是时候软件复位 UART,为 1 的时候表示复位完成。复位完成以后此位会自动置 1, 表示复位完成。此位只能写 0,写 1 会被忽略掉。

UARTx_UCR3


RXDMUXSEL(bit2): 始终为1

UARTx_USR2


寄存器 UARTx_USR2 用到的重要位如下:
**TXDC(bit3):**发送完成标志位,为 1 的时候表明发送缓冲(TxFIFO)和移位寄存器为空,也就是发送完成,向 TxFIFO 写入数据此位就会自动清零。
**RDR(bit0):**数据接收标志位,为 1 的时候表明至少接收到一个数据,从寄存器UARTx_URXD 读取数据接收到的数据以后此为会自动清零。

UARTx_UFCR 、 UARTx_UBIR 和 UARTx_UBMR

UARTx_UFCR 中我们要用到的是位 RFDIV(bit9:7),用来设置参考时钟分频

这三个寄存器设置UART的波特率,波特率的计算公式如下:

Ref Freq: 经过分频以后进入 UART 的最终时钟频率。
UBMR: 寄存器 UARTx_UBMR 中的值。
UBIR: 寄存器 UARTx_UBIR 中的值。

比如现在要设置 UART 波特率为 115200,那么可以设置 RFDIV 为5(0b101),也就是 1 分频,因此 Ref Freq=80MHz。设置 UBIR=71, UBMR=3124,根据上面的公式可以得到:

UARTx_URXD 和 UARTx_UTXD

UARTx_URXD 和 UARTx_UTXD,这两个寄存器分别为 UART 的接收和发送数据寄存器,这两个寄存器的低八位为接收到的和要发送的数据。读取寄存器UARTx_URXD 即可获取到接收到的数据,如果要通过 UART 发送数据,直接将数据写入到寄存器 UARTx_UTXD 即可。

3.UART1 的配置

1、设置 UART1 的时钟源
设置 UART 的时钟源为 pll3_80m,设置寄存器 CCM_CSCDR1 的 UART_CLK_SEL 位为 0即可。
2、初始化 UART1
初始化 UART1 所使用 IO,设置 UART1 的寄存器 UART1_UCR1~UART1_UCR3,设置内容包括波特率,奇偶校验、停止位、数据位等等。
3、使能 UART1
UART1 初始化完成以后就可以使能 UART1 了,设置寄存器 UART1_UCR1 的位 UARTEN为 1。
4、编写 UART1 数据收发函数
编写两个函数用于 UART1 的数据收发操作

下面是相关的函数

/** @description : 初始化串口1,波特率为115200* @param       : 无* @return       : 无*/
void uart_init(void)
{/* 1、初始化串口IO           */uart_io_init();/* 2、初始化UART1              */uart_disable(UART1);  /* 先关闭UART1         */uart_softreset(UART1);    /* 软件复位UART1        */UART1->UCR1 = 0;      /* 先清除UCR1寄存器 *//** 设置UART的UCR1寄存器,关闭自动波特率* bit14: 0 关闭自动波特率检测,我们自己设置波特率*/UART1->UCR1 &= ~(1<<14);/** 设置UART的UCR2寄存器,设置内容包括字长,停止位,校验模式,关闭RTS硬件流控* bit14: 1 忽略RTS引脚* bit8: 0 关闭奇偶校验* bit6: 0 1位停止位* bit5: 1 8位数据位* bit2: 1 打开发送* bit1: 1 打开接收*/UART1->UCR2 |= (1<<14) | (1<<5) | (1<<2) | (1<<1);/** UART1的UCR3寄存器* bit2: 1 必须设置为1!参考IMX6ULL参考手册3624页*/UART1->UCR3 |= 1<<2; /** 设置波特率* 波特率计算公式:Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)) * 如果要设置波特率为115200,那么可以使用如下参数:* Ref Freq = 80M 也就是寄存器UFCR的bit9:7=101, 表示1分频* UBMR = 3124* UBIR =  71* 因此波特率= 80000000/(16 * (3124+1)/(71+1))=80000000/(16 * 3125/72) = (80000000*72) / (16*3125) = 115200*/UART1->UFCR = 5<<7; //ref freq等于ipg_clk/1=80MhzUART1->UBIR = 71;UART1->UBMR = 3124;#if 0uart_setbaudrate(UART1, 115200, 80000000); /* 设置波特率 */
#endif/* 使能串口 */uart_enable(UART1);
}/** @description : 初始化串口1所使用的IO引脚* @param        : 无* @return       : 无*/
void uart_io_init(void)
{/* 1、初始化IO复用 * UART1_RXD -> UART1_TX_DATA* UART1_TXD -> UART1_RX_DATA*/IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0);    /* 复用为UART1_TX */IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0); /* 复用为UART1_RX *//* 2、配置UART1_TX_DATA、UART1_RX_DATA的IO属性 *bit 16:0 HYS关闭*bit [15:14]: 00 默认100K下拉*bit [13]: 0 keeper功能*bit [12]: 1 pull/keeper使能*bit [11]: 0 关闭开路输出*bit [7:6]: 10 速度100Mhz*bit [5:3]: 110 驱动能力R0/6*bit [0]: 0 低转换率*/IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0);IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0);
}/** @description      : 波特率计算公式,*                        可以用此函数计算出指定串口对应的UFCR,*                           UBIR和UBMR这三个寄存器的值* @param - base     : 要计算的串口。* @param - baudrate   : 要使用的波特率。* @param - srcclock_hz   :串口时钟源频率,单位Hz* @return      : 无*/
void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz)
{uint32_t numerator = 0u;      //分子uint32_t denominator = 0U;     //分母uint32_t divisor = 0U;uint32_t refFreqDiv = 0U;uint32_t divider = 1U;uint64_t baudDiff = 0U;uint64_t tempNumerator = 0U;uint32_t tempDenominator = 0u;/* get the approximately maximum divisor */numerator = srcclock_hz;denominator = baudrate << 4;divisor = 1;while (denominator != 0){divisor = denominator;denominator = numerator % denominator;numerator = divisor;}numerator = srcclock_hz / divisor;denominator = (baudrate << 4) / divisor;/* numerator ranges from 1 ~ 7 * 64k *//* denominator ranges from 1 ~ 64k */if ((numerator > (UART_UBIR_INC_MASK * 7)) || (denominator > UART_UBIR_INC_MASK)){uint32_t m = (numerator - 1) / (UART_UBIR_INC_MASK * 7) + 1;uint32_t n = (denominator - 1) / UART_UBIR_INC_MASK + 1;uint32_t max = m > n ? m : n;numerator /= max;denominator /= max;if (0 == numerator){numerator = 1;}if (0 == denominator){denominator = 1;}}divider = (numerator - 1) / UART_UBIR_INC_MASK + 1;switch (divider){case 1:refFreqDiv = 0x05;break;case 2:refFreqDiv = 0x04;break;case 3:refFreqDiv = 0x03;break;case 4:refFreqDiv = 0x02;break;case 5:refFreqDiv = 0x01;break;case 6:refFreqDiv = 0x00;break;case 7:refFreqDiv = 0x06;break;default:refFreqDiv = 0x05;break;}/* Compare the difference between baudRate_Bps and calculated baud rate.* Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).* baudDiff = (srcClock_Hz/divider)/( 16 * ((numerator / divider)/ denominator).*/tempNumerator = srcclock_hz;tempDenominator = (numerator << 4);divisor = 1;/* get the approximately maximum divisor */while (tempDenominator != 0){divisor = tempDenominator;tempDenominator = tempNumerator % tempDenominator;tempNumerator = divisor;}tempNumerator = srcclock_hz / divisor;tempDenominator = (numerator << 4) / divisor;baudDiff = (tempNumerator * denominator) / tempDenominator;baudDiff = (baudDiff >= baudrate) ? (baudDiff - baudrate) : (baudrate - baudDiff);if (baudDiff < (baudrate / 100) * 3){base->UFCR &= ~UART_UFCR_RFDIV_MASK;base->UFCR |= UART_UFCR_RFDIV(refFreqDiv);base->UBIR = UART_UBIR_INC(denominator - 1); //要先写UBIR寄存器,然后在写UBMR寄存器,3592页 base->UBMR = UART_UBMR_MOD(numerator / divider - 1);}
}/** @description : 关闭指定的UART* @param - base: 要关闭的UART* @return      : 无*/
void uart_disable(UART_Type *base)
{base->UCR1 &= ~(1<<0);
}/** @description : 打开指定的UART* @param - base: 要打开的UART* @return      : 无*/
void uart_enable(UART_Type *base)
{base->UCR1 |= (1<<0);
}/** @description : 复位指定的UART* @param - base: 要复位的UART* @return      : 无*/
void uart_softreset(UART_Type *base)
{base->UCR2 &= ~(1<<0);           /* UCR2的bit0为0,复位UART        */while((base->UCR2 & 0x1) == 0); /* 等待复位完成                    */
}/** @description : 发送一个字符* @param - c    : 要发送的字符* @return      : 无*/
void putc(unsigned char c)
{while(((UART1->USR2 >> 3) &0X01) == 0);/* 等待上一次发送完成 */UART1->UTXD = c & 0XFF;               /* 发送数据 */
}/** @description : 发送一个字符串* @param - str : 要发送的字符串* @return     : 无*/
void puts(char *str)
{char *p = str;while(*p)putc(*p++);
}/** @description : 接收一个字符* @param        : 无* @return       : 接收到的字符*/
unsigned char getc(void)
{while((UART1->USR2 & 0x1) == 0);/* 等待接收完成 */return UART1->URXD;                /* 返回接收到的数据 */
}/** @description : 防止编译器报错* @param       : 无* @return       : 无*/
void raise(int sig_nr)
{}

【ARM】IMX6UL串口通信相关推荐

  1. arm linux串口控制led,通信程序设计 - Linux下ARM和单片机的串口通信设计

    3 通信程序设计 ARM 与单片机的串口通信程序包括两方面: 一方面是作为上位机的ARM 的串口通信程序,另一方面是作为下位机的单片机的串口通信程序.在通信之前必须制定合理的通信协议以保证通信的可靠性 ...

  2. TQ2440(ARM)和SIM300(GPRS模块)串口通信

    TQ2440(ARM)和SIM300(GPRS模块)串口通信 三月 15th, 2012 Linux平台开发 • 毕业论文 • 编程技术 1 Comment 最近在做串口通信这快遇到了很大的麻烦.现在 ...

  3. ARM内核单片机的串口通信(UART)使用(数据的收发)

    ARM内核单片机的串口通信(UART)使用 进入正题: 首先,要明白使用UART进行通信,无论收发数据,传输的都是16进制.而中文.英文.标点符号其本质都是16进制,只是一个中文需要用两个字节表示,一 ...

  4. ARM芯片(S5PV210芯片)——串口通信详解

    1.电子通信的基本概念 1.1.同步通信和异步通信 1.同步通信:通信双方有统一的工作节拍,一般需要发送方给接收方发送信息的同时发送时钟信号,接收方根据发送方给它的时钟信号来安排自己的工作节奏.同步通 ...

  5. NXP(I.MX6uLL) UART串口通信原理————这个未复习

    参考:Linux NXP (I.MX6uLL) UART串口通信原理 作者:一只青木呀 发布时间: 2020-09-20 16:48:33 网址:https://blog.csdn.net/weixi ...

  6. linux 嵌入式串口通信设计目的,基于linux的嵌入式串口通信.doc

    PAGE 天津电子信息职业技术学院 <嵌入式软件编程>课程报告 课程名称:基于linux的嵌入式串口通信 课程代码: 115229 姓 名: 甘琦 学 号: 48 专 业: 物联网应用技术 ...

  7. linux 嵌入式串口通信,基于linux的嵌入式串口通信综述.doc

    PAGE 天津电子信息职业技术学院 <嵌入式软件编程>课程报告 课程名称:基于linux的嵌入式串口通信课程代码: 115229 姓 名: 甘琦 学 号: 48 专 业: 物联网应用技术 ...

  8. 串口通信Serial

    基础知识 ASCII 表 | 菜鸟教程 (runoob.com) hex取值范围:不同编码有不同的解码范围,超过范围则无法解码 串口通信分类 一.并行通信 8位数据同时通过并行线进行传送,传输速率较高 ...

  9. GD32串口通信注意事项

    GD32串口通信 虽说GD32与stm32采用同样的ARM® Cortex®-M3内核,而且GD32很大程度上可兼容stm32的程序,但是也存在着一些差异:所以为了使用上减少出错,使用GD32时尽量采 ...

最新文章

  1. SpringBoot项目打包war部署到服务器去掉项目名所遇到的坑
  2. Linus:Linux太烂,我要删了它,你们用Windows XP吧!
  3. Android View measure(0,0)的作用
  4. 计算机不会输入函数怎么办,函数不正确_电脑上文件打不开,显示函数不正确怎么解决?...
  5. 用BlockingExecutor限制任务提交
  6. 划分vlan实验心得体会_思科:相同vlan,不同交换机之间的通信
  7. ThreadLocal类学习笔记
  8. ASP.NET ActionPack
  9. idea/eclipse/vscode同时搜索多个文件类型
  10. 【Proteus仿真8086】往8086 内存中写入数据
  11. Tableau Desktop【包含各个版本】
  12. vpp flowprobe
  13. 连通区域的边界点程序
  14. 科研狗工具大合集,赶紧集合看过来
  15. 如何在各种非三星电脑上安装Samsung Notes三星笔记
  16. Python销售管理系统
  17. 【云原生】风云暗涌的时代,DBA们的利刃出鞘了
  18. android camera 对焦大小,Android camera2对焦设置
  19. 小程序的影响到底有多大?
  20. s5pv210的工作模式

热门文章

  1. Python安装Selenium
  2. 基于 web 的单视图三维重建可视化系统
  3. Hoeffding 不等式
  4. 二进制数据转换为十六进制字符串
  5. 为什么要对数据进行归一化处理
  6. 微信怎么查计算机成绩查询,如何用微信免费查询自己的成绩?——易查分快速帮您实现...
  7. 机器学习20:基于ResNet50和FaceNet实现人脸识别
  8. 社交网站如何免接口启用QQ微信“一键登录”网站
  9. 2014-2022年4月全国空气质量数据分析
  10. 爬虫项目实战二:爬取起点小说网