1.UART
1.1IMX6ULL的UART(通用异步收发传输器)模块框图UART(通用异步收发传输器)模块的框图

数据终端设备和数据电路终接设备

底板原理图:


1.2UART寄存器
1.2.1UARTx_URXD接受寄存器

1.2.2UARTx_UTXD发送寄存器

1.2.3UARTx_UCR1控制寄存器 1

1.2.4UARTx_UCR2控制寄存器 2

1.2.5UARTx_UCR3控制寄存器 3

1.2.6UART_xUFCRFIFO 控制寄存器

1.2.7UARTx_USR2状态寄存器

1.2.8UARTx_UBIR波特率整数部分寄存器

1.2.9UARTx_UBMR波特率小数部分寄存器


1.3配置UART


void init_uart1()
{
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);//电器属性
UART1 -> UCR1 = 0;//先给ucr1第零位清零,关闭uart
UART1 ->UCR2 = 0;
//第0位清零,准备让 UART 开始工作时,让它经历一次复位
//第八位清零,无校验
//第六位清零,1位停止位
UART1 ->UCR2 |= (1 << 14) |(1 << 5)|(1 << 2)|(1 << 1);
//第14位置1,一直接收,不管缓冲区是不是满的
//第五位置1,传输8位数据位
//第二位第一位置1,打开发送和接收
UART1->UCR3 |= (1 << 2);//交叉使能
UART1->UFCR = (5 << 7);//预分频1
UART1->UBIR = 999;
UART1->UBMR = 43401;
//i.MX6ULL 的 UART 波特率计算公式(UBMR + 1) / (UBIR + 1) = RefFreq / 16 * BaudRate
//带入RefFreq=80M,BaudRate = 115200
UART1->UCR1 |= (1 << 0);//使能uart
}
配置好后,再来编写发送字符串函数:

实现每秒发送一次字符串:

再来编写接收函数:


2.I2C
IICBus简称,所以中文应该叫集成电路总线。是飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展而来的一种同步串行半双工通信总线方式。该总线允许同时连接多个设备(芯片)。每块芯片在总线上拥有特定的地址。I²C 是用 SCL(时钟线) + SDA (数据线)两根线,这两个信号线都是双向的,通过起始/停止条件和地址寻址,完成半双工串行通信的芯片间总线,适合连接 EEPROM、传感器、RTC 等低速外设。

**注意!一定要在scl和sda上面分别接一个上拉电阻,**I²C 使用开漏输出,设备只能通过"拉低"或"释放";上拉电阻把"释放"变成高电平,因此总线空闲必须靠上拉拉到高。

IIC通信时序图:

按照I2C标准,主设备发起通信时先发送一个起始信号,之后发送的第一个字节就是子设备的设备地址。需要注意的是。设备地址本身只占7个比特,最后一个比特所代表的是之后的数据流向。0代表主发从收,通常描述为写,1表示从发主收,通常描述为读。
例如,某个设备的从机地址为0x48(二进制0100 1000b),主机在发送完起始信号之后要发送要发送的从机地址其实是1001 000x,这里x就是数据流向位。如果x为0,表示接下来主机发送数据,从机接收数据。如果x为1,表示接下要求从机发送数据,主机接收数据。
2.1EEPROM
eeprom设备地址:

是一种 可电擦写、掉电不丢数据 的小容量非易失存储器,常在开发板上通过 I²C 总线 连接。
向eeprom存数据时序图:

页写同理:

从eeprom读数据时序图:

对某设备的某字节后的n个字节进行读取,原理相同。

2.2IIC寄存器
2.2.1I2Cx_IFDR
I²C 控制器用一个 **Peripheral Clock(ipg_perclk)** 分频得到 SCL

2.2.2I2Cx _I2CR
打开 I²C、设主/从、产生 START/STOP

2.2.3I2Cx _I2SR
轮询,用来判断"事情做完没"ack/nack

2.2.4I2Cx _I2DR
发送地址 / 数据,或读取接收数据

2.3iic初始化

首先设置引脚复用以及初始化:

2.4写设备以及读设备

按照流程图完成写和读:
cs
void i2c_write(I2C_Type *base, unsigned char device_address, unsigned char reg_address, const unsigned char *data, int len)
{
base->I2SR &= ~((1 << IAL) | (1 << IIF)); // 清除仲裁丢失标志和中断标志
while((base->I2SR & (1 << ICF)) == 0); // 等待传输完成标志为空闲
base->I2CR |= (1 << MSTA) | (1 << MTX); // 设置为主机模式并设为发送模式
base->I2CR &= ~(1 << TXAK); // 设置发送应答使能
base->I2SR &= ~(1 << IIF); // 清除中断标志
base->I2DR = device_address << 1; // 发送设备地址(写方向)
while((base->I2SR & (1 << IIF)) == 0); // 等待发送完成中断
base->I2SR &= ~(1 << IIF); // 清除中断标志
base->I2DR = reg_address; // 发送寄存器地址
while((base->I2SR & (1 << IIF)) == 0); // 等待发送完成中断
while(len--) // 循环发送数据
{
base->I2SR &= ~(1 << IIF); // 清除中断标志
base->I2DR = *data++; // 发送一个字节数据并移动指针
while((base->I2SR & (1 << IIF)) == 0); // 等待发送完成中断
}
base->I2CR &= ~(1 << MSTA); // 清除主机模式标志,释放总线
while((base->I2SR & (1 << IBB)) != 0) // 等待总线忙标志清除
{
delayus(100); // 延时等待总线释放
}
}
void i2c_read(I2C_Type *base, unsigned char device_address, unsigned char reg_address, unsigned char *data, int len)
{
base->I2SR &= ~((1 << IAL) | (1 << IIF)); // 清除仲裁丢失标志和中断标志
while((base->I2SR & (1 << ICF)) == 0); // 等待传输完成标志为空闲
base->I2CR |= (1 << MSTA) | (1 << MTX); // 设置为主机模式并设为发送模式
base->I2CR &= ~(1 << TXAK); // 设置发送应答使能
base->I2SR &= ~(1 << IIF); // 清除中断标志
base->I2DR = device_address << 1; // 发送设备地址(写方向)
while((base->I2SR & (1 << IIF)) == 0); // 等待发送完成中断
base->I2SR &= ~(1 << IIF); // 清除中断标志
base->I2DR = reg_address; // 发送寄存器地址
while((base->I2SR & (1 << IIF)) == 0); // 等待发送完成中断
base->I2CR |= (1 << RSTA); // 产生重复起始条件
base->I2SR &= ~(1 << IIF); // 清除中断标志
base->I2DR = device_address << 1 | 1; // 发送设备地址(读方向)
while((base->I2SR & (1 << IIF)) == 0); // 等待发送完成中断
base->I2CR &= ~(1 << MTX); // 切换为接收模式
base->I2SR &= ~(1 << IIF); // 清除中断标志
if(1 == len) // 如果只读一个字节
{
base->I2CR |= (1 << TXAK); // 设置发送非应答,表示最后一个字节
}
*data = base->I2DR; // 伪读取一次以启动接收
while(len-- != 0) // 循环接收数据
{
while((base->I2SR & (1 << IIF)) == 0); // 等待接收完成中断
base->I2SR &= ~(1 << IIF); // 清除中断标志
if(len == 0) // 如果是最后一个字节
{
base->I2CR &= ~((1 << MSTA) | (1 << TXAK)); // 清除主机标志和发送应答标志,停止传输
while((base->I2SR & (1 << IBB)) != 0) // 等待总线忙标志清除
{
delayus(100); // 延时等待总线释放
}
}
else if(len == 1) // 如果还剩一个字节
{
base->I2CR |= (1 << TXAK); // 设置发送非应答
}
*data++ = base->I2DR; // 读取一个字节数据并移动指针
}
}
2.5LM75

读取lm75温度传感器的温度(两个字节)
、
再用读取的两个字节计算出真实温度



lm75.c:
#include"lm75.h"
#include"i2c.h"
#include"MCIMX6Y2.h"
float lm75_get_temperature(void)
{
unsigned char buffer[2] = {0};
short s;
struct I2C_MSG msg =
{
.deiection = I2C_Read,
.dev_address = 0x48,
.reg_address = 0,
.reg_len = 1,
.data = buffer,
.len = 2
};
xfer(I2C1, &msg);
// i2c_read(I2C1, 0x48, 0, 1, buffer, 2);
s = buffer[0] << 8;
s |= buffer[1];
s >>= 7;
return s * 0.5;
}