通用同步异步收发器(USART)
USART介绍
- 全双工的异步通信。
- 接口通过三个引脚与其余设施连贯在一起(接管RX、发送TX、时钟输入CK)(任何USART双向通信至多须要RX和TX)
- 发送方为同步传输提供时钟。
- 发送和接管由一共用的波特率发生器驱动,当发送器和接收器的使能位别离置位时,别离为其产生时钟。
-
波特率
- 应用分数波特率发生器零碎
- 发送和接管共用的可编程波特率,最高达4.5Mbits/s
- 12位整数和4位小数的示意办法。
- 只有USART1应用PCLK2(即APB2最高72MHz)。其它USART应用PCLK1(即APB1最高36MHz)。
- 可编程数据字长度(8位或9位)(8数据+n进行位/9数据+n进行位)(数据位最初一个可能是奇偶校验位)(数据最低无效位在前)
- 可配置的进行位-反对1或2个进行位。
-
发送和接收数据流程:(数据寄存器USART_DR蕴含发送寄存器TDR和接管寄存器RDR)
- 发送数据:零碎进行写操作将数据写入发送寄存器TDR,而后TDR将数据移送到发送移位寄存器中,再由发送移位寄存器送入编解码模块中编码后从TX输入。
- 接收数据;数据从RX进入,先到编解码模块中解码后送入接管移位寄存器,而后再到接管寄存器RDR中供零碎进行读操作。
- 当发送使能位(TE)被设置时,发送移位寄存器中的数据在TX脚上输入,相应的时钟脉冲在CK脚上输入。
- 留神:在数据传输期间不能复位TE位,否则将毁坏TX脚上的数据,因为波特率计数器进行计数。正在传输的以后数据将失落。
分数波特率的计算
- 波特率 = PCK /(16*USARTDIV)(USARTDIV是波特比率寄存器中的值换算失去,即分频系数)
-
已知USARTDIV = 25.62;求波特比率寄存器USART_BRR该写入的值。
- DIV_Fraction = 16*0.62 = 9.92。最靠近的整数是:10 = 0xA
- DIV_Mantissa = 取整(25.620) = 25 = 0x019。(整数局部是12位所以是0x019,写0x19也行,这里是为了好分别)、
- 所以USART_BRR = 0x019A(写作0x19A也行)
USART的中断请求
- USART的各种中断事件被连贯到同一个中断向量
-
以下各种状况会触发中断:(如果设置了对应的使能管制位,这些事件就能够产生各自的中断)
- 发送期间:发送实现、革除发送、发送数据寄存器为空。
- 接管期间:闲暇总线检测、溢出谬误、接收数据寄存器非空、校验谬误、LIN断开符号检测、乐音标记(仅在多缓冲器通信)和帧谬误(仅在多缓冲器通信)。
USART寄存器
状态寄存器(USART_SR)
- 复位值:0x00C0
-
TXE:发送寄存器DTR是否为空标记位。
- 当TDR寄存器中的数据被硬件转移到移位寄存器的时候,该位被硬件置位。
- 如果管制寄存器USART_CR1中的TXEIE为1,则产生中断。
- 对数据寄存器USART_DR的写操作,硬件会将该位清零。
- 1:数据曾经被转移到移位寄存器。
-
TC:发送实现标记位。
- 当一帧数据发送实现后,并且TXE=1时,该位被硬件置一。
- 如果管制寄存器USART_CR1中的TXEIE为1,则产生中断。
- 由软件序列革除该位(先读USART_SR,而后写入USART_DR)
- 1:发送实现。
-
RXNE:查看接管移位寄存器是否为空标记位。
- 当接管移位寄存器中的数据被转移到接收数据寄存器RDR中时,该位被硬件置位(接管移位寄存器中为空)
- 如果管制寄存器USART_CR1中的RXNEIE为1,则产生中断。
- 对数据寄存器USART_DR的读操作能够将该位清零。
- 1:收到数据,能够读出。
-
IDLE:监测到总线闲暇标记位。
- 当检测到总线闲暇时,该位被硬件置位。
- 如果USART_CR1中的IDLEIE为1,则产生中断。
- 由软件序列革除该位(先读USART_SR,而后读USART_DR)。
- 1:检测到闲暇总线。
数据寄存器(USART_DR)
- 复位值:不确定
- DR:数据值,蕴含了发送或接管的数据。
波特比率寄存器(USART_BRR)
- 复位值:0x0000
- DIV_Mantissa:USARTDIV的整数局部
- DIV_Fraction:USARTDIV的小数局部
管制寄存器 1(USART_CR1)
- 复位值:0x0000
- UE:USART使能位。该位由软件设置和清零。(0:USART分频器和输入被禁止)
- M:设置传输字长,由软件对其设置和清零(0:8个数据位。1:9个数据位)
- PCE:测验管制使能(1:使能校验管制)
- PS:校验抉择(0:偶校验)
- PEIE:PE中断使能(1:当USART_SR中的TXE为1时,产生USART中断)
- TCIE:发送实现中断使能(1:当USART_SR中的TC为1时,产生USART中断)
- RXNEIE:接管移位寄存器为空的中断使能(1:当USART_SR中的ORE或者RXNE为1时,产生USART中断)
- IDLEIE:总线闲暇IDLE中断使能(该位由软件设置或革除)(1:当USART_SR中的IDLE为1时,产生USART中断)
- TE:发送使能(1:使能发送)
- RE:接管使能(1:使能接管,并开始搜查RX引脚上的起始位)
管制寄存器 2(USART_CR2)
- 复位值:0x0000
-
STOP:进行位(UART4和UART5不能用0.5进行位和1.5进行位)
- 00:1个进行位。
- 01:0.5个进行位。
- 10:2个进行位。
- 11:1.5个进行位
- CLKEN:时钟使能(0:禁止CK引脚)
代码示例
- USART初始化设置
/*******************************************************************************
* 函 数 名 : USART1_Init
* 函数性能 : USART1初始化函数
* 输 入 : bound:波特率
* 输 出 : 无
*******************************************************************************/
void USART1_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure; //申明GPIO对象
USART_InitTypeDef USART_InitStructure; //申明串口对象
NVIC_InitTypeDef NVIC_InitStructure; //申明嵌套断的对象
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输入PA9
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输入
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入PA9*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输出PA10
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模仿输出
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输出PA10*/
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = bound;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个进行位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流管制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC); //革除串口的挂起标记
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相干中断
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //依据指定的参数初始化VIC寄存器、
}
- 串口的中断函数
/*******************************************************************************
* 函 数 名 : USART1_IRQHandler
* 函数性能 : USART1中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 r;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接管中断
{
r =USART_ReceiveData(USART1);//(USART1->DR); //读取接管到的数据
USART_SendData(USART1,r); // 将接管到的数据再发送回去
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
}
USART_ClearFlag(USART1,USART_FLAG_TC);
}
I2C通信之EEPROM
I2C特点
- 遵循着与51单片机雷同的I2C协定。
- 接口通过数据引脚(SDA)和时钟引脚(SCL)连贯到I2C总线(数据引脚SDA用于数据传输,时钟引脚SCL用于收发数据的同步)
- I2C模块接管和发送数据,并将数据从串行转换成并行,或并行转换成串行。
-
I2C主设施性能:
- 产生时钟。
- 产生起始和进行信号。
-
I2C从设施性能:
- 可编程的I2C地址检测。
- 可响应2个从地址的双地址能力。
- 进行位检测。
-
反对不同的通信速度:
- 规范速度(高达100 kHz)
- 疾速(高达400 kHz)
-
状态标记:
- 发送器/接收器模式标记。
- 字节发送完结标记。
- I2C总线忙标记。
-
谬误标记:
- 主模式时的仲裁失落。
- 地址/数据传输后的应答(ACK)谬误。
- 检测到错位的起始或进行条件。
- 禁止拉长时钟性能时的上溢或下溢。
-
领有2个中断向量:
- 1个中断用于地址/数据通讯胜利。
- 1个中断用于谬误。
I2C通信流程
1.主机发送I2C起始信号(通过SDA线)并产生时钟信号,通知从机要开始传输信号了(所有从机都会收到这个起始信号)
2.此时主机会播送从机地址(每个从机地址惟一)(跟在起始条件之后的1个或2个字节就是地址),匹配到后与之对应的从机地址会给出一个应答信号。
3.在发送从地址时,设施也会告知从设施是发送数据还是接收数据(TRA位标记主设施是在接收器模式还是发送器模式)
4.在7位地址模式时:- 进入发送数据模式:主设施发送从地址时最低位为’0’。
- 进入接收数据模式:主设施发送从地址时最低位为’1’。
5.在10位地址模式时:
- 进入发送数据模式:主设施先送头字节(11110xx0),而后送最低位为’0’的从地址(这里xx代表10位地址中的最高2位)
- 进入接收数据模式:主设施先送头字节(11110xx0),而后送最低位为’1’的从地址。而后再从新发送一个开始条件,前面跟着头字节(11110xx1)(这里xx代表10位地址中的最高2位)
6.从器件地址约定:
- 8位从器件地址的高4位固定为1010,接下来的3位示意要读写存储器的地址,最初一位为读写管制位(1示意读)
7.如果从机许可的话就能够进行通信了。
8.在进行通信时,主机会发送进行信号,通知从机到此结束。
I2C模式抉择
-
四种运行模式:(该模块默认地工作于从模式)
- 从发送器模式
- 从接收器模式
- 主发送器模式
- 主接收器模式
- 留神:接口在生成起始条件后主动地从从模式切换到主模式;当仲裁失落或产生进行信号时,则从主模式切换到从模式。
- 数据传输流程:串行数据传输总是以起始条件开始并以进行条件完结,并且在一个字节传输的8个时钟后的第九个时钟,接收器必须回应一个应答信号(ACK)给发送器。当通过START位在总线上产生了起始条件,设施就进入了主模式。(设施默认从模式)
I2C中断请求
- SB、ADDR、ADD10、STOPF、BTF、RxNE和TxE通过逻辑或应用同一个中断通道(it_event事件中断)
- BERR、ARLO、AF、OVR、PECERR、TIMEOUT和SMBALERT通过逻辑或应用同一个中断通道(it_error谬误中断)
I2C寄存器形容
管制寄存器1 (I2C_CR1)
- 复位值:0x0000
-
SWRST:软件复位
- 当被置位时,I2C处于复位状态。在复位该位前确信I2C的引脚被开释,总线是空的
- 0:I2C模块不处于复位状态
- 1: I2C模块处于复位状态
-
ACK:应答使能
- 软件能够设置或革除该位,或当PE=0时,由硬件革除
- 0:无应答返回
- 1:在接管到一个字节后返回一个应答(匹配的地址或数据)
-
STOP:进行条件产生
- 软件能够设置或革除该位
- 当检测到进行条件时,由硬件革除
- 当检测到超时谬误时,硬件将其置位
- 在主模式下:1:在以后字节传输或在以后起始条件收回后产生进行条件
- 在从模式下:1:在以后字节传输或开释SCL和SDA线后产生进行条件
- 留神:当设置了STOP、START或PEC位,在硬件革除这个位之前,软件不要执行任何对I2C_CR1的写操作;否则有可能会第2次设置STOP、START或PEC位
-
START:起始条件产生
- 软件能够设置或革除该位
- 当起始条件收回后或PE=0时,由硬件革除
- 在主模式下:1:反复产生起始条件
- 在从模式下:1:当总线闲暇时,产生起始条件
- ENGC:播送呼叫使能(1:容许播送呼叫. 以应答响应地址00h)
- ENPEC:PEC使能(ENPEC:PEC使能)
-
ENARP:ARP使能
- 1:使能ARP
- 如果SMBTYPE=0,应用SMBus设施的默认地址
- 如果SMBTYPE=1,应用SMBus的主地址
- SMBTYPE:SMBUS类型(0:SMBus设施;1:SMBUS主机)
- SMBUS:SMBUS模式(0:I2C模式;1:SMBUS模式)
- PE:I2C模块使能(1:启用I2C模块,依据SMBUS位的设置,相应的I/O口需配置为复用性能)
管制寄存器 2(I2C_CR2)
- 复位值:0x0000
- LAST: DMA最初一次传输(1:下一次DMA的EOT是最初的传输)
- DMAEN:DMA申请使能(1:当TxE=1或RxNE =1时,容许DMA申请)
- ITBUFEN:缓冲器中断使能(1:当TxE=1或RxNE=1时,产生事件中断,不论DMAEN是何种状态)
- ITEVTEN:事件中断使能(1:容许事件中断)
- ITERREN:出错中断使能(1:容许出错中断)
-
FREQ[5:0]:I2C模块时钟频率(必须设置正确的输出时钟频率产生正确的时序,范畴在2~36MHz之间)
- 000000:禁用
- 000001:禁用
- 000010:2MHz
- …….
- 100100:36MHz
- 大于100100:禁用
本身地址寄存器 1(I2C_OAR1)
- 复位值:0x0000
-
ADDMODE:寻址模式(在从模式中)
- 0:7位从地址(不响应10位地址)
- 1:10位从地址(不响应7位地址)
- 位14:必须始终由软件放弃为1。
-
ADD[9:8]:接口地址
- 7位地址模式时不必关怀
- 10位地址模式时为地址的9~8位
- ADD[7:1]:接口地址(地址的7~1位)
-
ADD0:接口地址
- 7位地址模式时不必关怀
- 10位地址模式时为地址第0位
数据寄存器(I2C_DR)
- 复位值:0x0000
-
DR:8位数据寄存器
- 用于寄存接管到的数据或搁置用于发送到总线的数据
状态寄存器 1(I2C_SR1)
- 复位值:0x0000
- SMBALERT:SMBus揭示
- TIMEOUT:超时或Tlow谬误
- PECERR:在接管时产生PEC谬误
- OVR:过载/欠载
- AF:应答失败
- ARLO:仲裁失落(主模式)
- BERR:总线出错
- TxE:数据寄存器为空(发送时)
- RxNE:数据寄存器非空(接管时)
- STOPF:进行条件检测位(从模式)
- ADD10:10位头序列已发送(主模式)
- BTF:字节发送完结
- ADDR:地址已被发送(主模式)/地址匹配(从模式)
- SB:是否发送起始条件(主模式)
状态寄存器 2 (I2C_SR2)
- 复位值:0x0000
- PEC[7:0]:数据包出错检测
- DUALF:双标记(从模式)
- SMBHOST: SMBus主机头系列(从模式)
- SMBDEFAULT:SMBus设施默认地址(从模式)
- GENCALL:播送呼叫地址(从模式)
- TRA:数据是否发送/接管
- BUSY:总线忙
- MSL:主从模式
时钟管制寄存器(I2C_CCR)
- 复位值:0x0000
-
留神:
- 要求FPCLK1该当是10 MHz的整数倍,这样能够正确地产生400KHz的疾速时钟
- CCR寄存器只有在敞开I2C时(PE=0)能力设置
- F/S:I2C主模式选项
- DUTY:疾速模式时的占空比
- CCR:疾速/规范模式下的时钟管制分频系数(主模式)
代码示例
- I2C代码
#include "iic.h"
#include "SysTick.h"
//IO操作函数
#define IIC_SCL PBout(10) //SCL
#define IIC_SDA PBout(11) //SDA
#define READ_SDA PBin(11) //输出SDA
/*******************************************************************************
* 函 数 名 : IIC_Init
* 函数性能 : IIC初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(IIC_SCL_PORT_RCC|IIC_SDA_PORT_RCC,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; //指定PB10作为SCL线
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化I/O口
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11; //指定PB11为SDA线
GPIO_Init(GPIOB,&GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
/*******************************************************************************
* 函 数 名 : SDA_OUT
* 函数性能 : SDA输入配置
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名 : SDA_IN
* 函数性能 : SDA输出配置
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名 : IIC_Start
* 函数性能 : 产生IIC起始信号
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IIC_Start(void)
{
SDA_OUT(); //SDA线输入
IIC_SDA=1; //SDA线拉高
IIC_SCL=1; //SCL线拉高
delay_us(5);
IIC_SDA=0; //当CLK值为高时,SDA由高变低示意起始信号
delay_us(6);
IIC_SCL=0; //钳住I2C总线,筹备发送或接收数据
}
/*******************************************************************************
* 函 数 名 : IIC_Stop
* 函数性能 : 产生IIC进行信号
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IIC_Stop(void)
{
SDA_OUT(); //sda线输入
IIC_SCL=0;
IIC_SDA=0;
IIC_SCL=1;
delay_us(6);
IIC_SDA=1; //当CLK值为高时,SDDA由低变高示意进行信号
delay_us(6);
}
/*******************************************************************************
* 函 数 名 : IIC_Wait_Ack
* 函数性能 : 期待应答信号到来
* 输 入 : 无
* 输 出 : 1,接管应答失败
0,接管应答胜利
*******************************************************************************/
u8 IIC_Wait_Ack(void)
{
u8 tempTime=0;
IIC_SDA=1;
delay_us(1);
SDA_IN(); //SDA设置为输出
IIC_SCL=1;
delay_us(1);
while(READ_SDA)
{
tempTime++;
if(tempTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输入0
return 0;
}
/*******************************************************************************
* 函 数 名 : IIC_Ack
* 函数性能 : 产生ACK应答
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
/*******************************************************************************
* 函 数 名 : IIC_NAck
* 函数性能 : 产生NACK非应答
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
/*******************************************************************************
* 函 数 名 : IIC_Send_Byte
* 函数性能 : IIC发送一个字节
* 输 入 : txd:发送一个字节
* 输 出 : 无
*******************************************************************************/
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
if((txd&0x80)>0) //0x80 1000 0000
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
/*******************************************************************************
* 函 数 名 : IIC_Read_Byte
* 函数性能 : IIC读一个字节
* 输 入 : ack=1时,发送ACK,ack=0,发送nACK
* 输 出 : 应答或非应答
*******************************************************************************/
u8 IIC_Read_Byte(u8 ack)
{
u8 i,receive=0;
SDA_IN();//SDA设置为输出
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
- AT24C代码
#include "24cxx.h"
#include "SysTick.h"
/*******************************************************************************
* 函 数 名 : AT24CXX_Init
* 函数性能 : AT24CXX初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void AT24CXX_Init(void)
{
IIC_Init();//IIC初始化
}
/*******************************************************************************
* 函 数 名 : AT24CXX_ReadOneByte
* 函数性能 : 在AT24CXX指定地址读出一个数据
* 输 入 : ReadAddr:开始读数的地址
* 输 出 : 读到的数据
*******************************************************************************/
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //发送写命令(最低位为0,对从器件写)
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址
}
else
{
IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据
}
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Start(); //反复的起始条件,从设施进入发送模式
IIC_Send_Byte(0XA1); //发送器件地址并且最初一位为1,对从器件读
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个进行条件
return temp;
}
/*******************************************************************************
* 函 数 名 : AT24CXX_WriteOneByte
* 函数性能 : 在AT24CXX指定地址写入一个数据
* 输 入 : WriteAddr :写入数据的目标地址
DataToWrite:要写入的数据
* 输 出 : 无
*******************************************************************************/
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址
}
else
{
IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
}
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个进行条件
delay_ms(10);
}
/*******************************************************************************
* 函 数 名 : AT24CXX_WriteLenByte
* 函数性能 : 在AT24CXX外面的指定地址开始写入长度为Len的数据
用于写入16bit或者32bit的数据
* 输 入 : WriteAddr :写入数据的目标地址
DataToWrite:要写入的数据
Len :要写入数据的长度2,4
* 输 出 : 无
*******************************************************************************/
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{
u8 t;
for(t=0;t<Len;t++)
{
AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
}
}
/*******************************************************************************
* 函 数 名 : AT24CXX_ReadLenByte
* 函数性能 : 在AT24CXX外面的指定地址开始读出长度为Len的数据
用于读出16bit或者32bit的数据
* 输 入 : ReadAddr :开始读出的地址
Len :要读出数据的长度2,4
* 输 出 : 读取的数据
*******************************************************************************/
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{
u8 t;
u32 temp=0;
for(t=0;t<Len;t++)
{
temp<<=8;
temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
}
return temp;
}
/*******************************************************************************
* 函 数 名 : AT24CXX_Check
* 函数性能 : 查看AT24CXX是否失常
* 输 入 : 无
* 输 出 : 1:检测失败,0:检测胜利
*******************************************************************************/
u8 AT24CXX_Check(void)
{
u8 temp;
temp=AT24CXX_ReadOneByte(255);//防止每次开机都写AT24CXX
if(temp==0x36)return 0;
else//排除第一次初始化的状况
{
AT24CXX_WriteOneByte(255,0X36);
temp=AT24CXX_ReadOneByte(255);
if(temp==0X36)return 0;
}
return 1;
}
/*******************************************************************************
* 函 数 名 : AT24CXX_Read
* 函数性能 : 在AT24CXX外面的指定地址开始读出指定个数的数据
* 输 入 : ReadAddr :开始读出的地址 对24c02为0~255
pBuffer :数据数组首地址
NumToRead:要读出数据的个数
* 输 出 : 无
*******************************************************************************/
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
while(NumToRead)
{
*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
NumToRead--;
}
}
/*******************************************************************************
* 函 数 名 : AT24CXX_Write
* 函数性能 : 在AT24CXX外面的指定地址开始写入指定个数的数据
* 输 入 : WriteAddr :开始写入的地址 对24c02为0~255
pBuffer :数据数组首地址
NumToRead:要读出数据的个数
* 输 出 : 无
*******************************************************************************/
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
while(NumToWrite--)
{
AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
}
}
发表回复