串口简述
全称:串行接口
别名:COM接口
工作方式:串行式逐位数据传输,两条线即可实现,一条发送,一个接收,一个GND,速度较低、
主要分类:
- UART(异步串口接收器)
- USART(同步步串口接收器)(多一个时钟线)
本片主要叙述UART
UART
全称:Universal Asynchronous Receiver/Trasmitter,异步串口接收器,包括了RS232、RS449、RS423、RS422和RS485等接口标准规范和总线标准规,即UART是异步串行通信口的总称。
原理:
把数据的字节按照比特顺序发送。另一端的UART把比特组装为字节。每个UART包含一个移位寄存器。通过一根线或其他媒介的串行通信比通过多根线的并行通信具有更低成本。
UART通常并不直接产生或接收其他设备的外部信号。独立接口设备用于转换信号的逻辑电平给UART。
通信可以是单工、全双工或半双工。
数据帧
位 | 说明 |
---|---|
空闲位 | 空闲状态,即没有数据传输,是高电平。(历史遗存) |
起始位 | 将数据线电位拉低表示开始数据传输。 |
数据位 | 实际传输的数据,可选5~8位,若按字节传输即一个字节8bit。低位在前,高位在后 |
奇偶检验位 | 可选。校验依据:判断传输的一组二进制数据中"1"的个数是奇数还是偶数 |
停止位 | 数据传输完成标志位,可选1~2位高电平 |
- 波特率:UART数据传输的速率(每秒传输的数据位数)
电平标准
逻辑电平 | TTL | RS-232 |
---|---|---|
逻辑0 | < 0.4V | -3~-15V |
逻辑1 | > 2.4V | +3~+15V |
时钟源选择
由寄存器CCM_CSCDR1 的 UART_CLK_SEL(bit)位来选择时钟源。
位 | 时钟源 |
---|---|
0 | pll3_80m(80MHz) |
1 | osc_clk(24M) |
由寄存器 CCM_CSCDR1 的 UART_CLK_PODF(bit5:0)设置分频值
可设置03F,对应164分频
主要寄存器
控制寄存器1——UARTx_UCR1(x=1~8)
位 | 描述 |
---|---|
ADBR(bit14) | 自动波特率检测使能位。为0关闭,为1使能 |
UARTEN(bit0) | UART 使能位。为0关闭,为1使能 |
控制寄存器2——UARTx_UCR2(x=1~8)
位 | 描述 |
---|---|
IRTS(bit14) | RTS引脚功能使能位。为0使能,为1忽略。(RTS(Request To Send):请求发送 ) |
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,使能 |
RXEN(bit1) | 接收使能位,为0,关闭UART的接收功能;为1,使能 |
SRST(bit0) | 软件复位,为0复位UART,为1表示复位完成(复位后自动完成) |
奇校验:一个字节8位中“1”的个数,校验位,添加一位,使9位中“1”的个数为奇数;偶校验同理。
控制寄存器3——UARTx_UCR3
根据手册说明,位 RXDMUXSEL(bit2),这个位应该始终为1。
状态寄存器2——UARTx_USR2
重要位说明:
- TXDC(bit3):发送完成标志位。为1,表示发送缓冲(TxFIFO)和移位寄存器为空(发送完成),写入数据则会清0。
- RDR(bit0):数据接收标志位。为1,表示至少接收到一个数据(已准备接收数据),为0,未准备好接收数据。
波特率设置相关寄存器
分频寄存器——UARTx_UFCR
重要位说明:
RFDIV(bit9:7) | 分频值 |
---|---|
000 | 6分频 |
001 | 5 |
010 | 4 |
011 | 3 |
100 | 2 |
101 | 1 |
111 | reserved |
增量寄存器——UARTx_UBMR
主要参数:UBMR
调制寄存器——UARTx_UBIR
主要参数:UBIR
根据以下公式可以设置波特率:
Baud Rate = Ref Freq / (16 * ((UBMR + 1) / (UBIR + 1))
- Ref Freq:经过分频以后进入 UART 的最终时钟频率
接收寄存器——UARTx_URXD
低8位为接收到的数据
发送寄存器——UARTx_UTXD
低8位为发送的数据
设置流程
- 设置时钟源
- 初始化UART
- 使能
- 编写收发函数
实验功能描述
上位机给开发板发送数据,开发板将收到的数据再返回给上位机。
程序实现
uart驱动文件:
/***************************
File name: bsp_delay.c
Author: ori
Version: v1.0
Description:串口驱动文件
Others: 无
log: ori 2021/2/4 参考正点例程
***************************/
#include "bsp_uart.h"
/*
* @description : 初始化串口1,波特率为115200
* @param : 无
* @return : 无
*/
void uart_init(void)
{
uart_io_init();
uart_disable(UART1);
uart_softreset(UART1);
UART1->UCR1 = 0; /* 清除UCR1寄存器 */
/*
* 设置UART的UCR1寄存器,关闭自动波特率
*/
UART1->UCR1 &= ~(1<<14);
/*
* 设置UART的UCR2寄存器
*/
UART1->UCR2 |= (1<<14) | (1<<5) | (1<<2) | (1<<1);
/*
* UART1的UCR3寄存器
*/
UART1->UCR3 |= 1<<2;
/*
* 设置波特率
*/
UART1->UFCR = 5<<7; //ref freq等于ipg_clk/1=80Mhz
UART1->UBIR = 71;
UART1->UBMR = 3124;
/* 使能串口 */
uart_enable(UART1);
}
/*
* @description : 初始化串口1所使用的IO引脚
* @param : 无
* @return : 无
*/
void uart_io_init(void)
{
IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0);
IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0);
/*
* 配置UART1_TX_DATA、UART1_RX_DATA的IO属性
*/
IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0);
}
/*
* @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);
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)
{
}
main文件
/***************************
File name: main.c
Author: ori
Version: v1.0
Description: 串口通信练习
Others: 无
log: 2021/2/4
***************************/
#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"
/*
* @description : main函数
* @param : 无
* @return : 无
*/
int main(void)
{
int_init(); /* 初始化中断*/
imx6u_clkinit(); /* 初始化系统时钟 */
clk_enable(); /* 使能所有的时钟 */
delay_init(); /* 初始化延时 */
led_init(); /* 初始化led */
beep_init(); /* 初始化beep*/
uart_init(); /* 初始化串口*/
unsigned char state = OFF;
unsigned char a = 0;
while(1)
{
puts("请输入一个字符:");
a = getc();
putc(a);
puts("\r\n");
puts("你输入的字符为:");
putc(a);
puts("\r\n");
puts("\r\n");
state = !state;
led_switch(LED0,state);
}
return 0;
}
编译烧录
结果
最后
本文多处参考正点原子的课程和资料(特表感谢)以及《i.MX 6UltraLite Applications Processor Reference Manual》,并在此基础上进了扩展和自己的理解,最后自己动手复原例程。