📄 at24x.c
字号:
#include "main.h"
#include "string.h"
#include "usart.h"
#include "AT24X.h"
#define ERROR (AT91C_TWI_NACK) //状态寄存器的一位,如果置1表示从机未应答
//*============================================================================
//* 函数名称:delay_ms
//* 函数功能:延时 ms
//* 入口参数:ms: 延时时间(ms)
//* 返回值 :无
//*============================================================================
void delay_ms(unsigned int ms)
{
unsigned int loop;
for (loop = 0; loop < 1000*ms; loop++);
}
//*============================================================================
//* TWI初始化
//*============================================================================
//*============================================================================
//* 函数名称:AT91F_SetTwiClock
//* 函数功能:设置TWI时钟
//* 入口参数:无
//* 返回值 :无
//*============================================================================
void AT91F_SetTwiClock(const AT91PS_TWI pTwi)
{
int sclock;
/* Here, CKDIV = 1 and CHDIV = CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6)*/
sclock = (10 * AT91C_MASTER_CLOCK /AT91C_TWI_CLOCK);
if (sclock % 10 >= 5)
sclock = (sclock /10) - 5;
else
sclock = (sclock /10)- 6;
sclock = (sclock + (4 - sclock %4)) >> 2; // div 4
pTwi->TWI_CWGR = 0x00010000 | sclock | (sclock << 8);
}
//*============================================================================
//* 函数名称: AT91F_TWI_Open
//* 函数功能: 打开 TWI
//*============================================================================
void AT91F_TWI_Open(void)
{
// 配制 PIO 为 TWI
AT91F_TWI_CfgPIO ();
AT91F_PIO_CfgOpendrain(AT91C_BASE_PIOA, AT91C_PA23_TWD | AT91C_PA24_TWCK); //配制 PA23,PA24 为开漏
// 使能 TWI 电源时钟
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_TWI );
// Configure TWI in master mode
AT91F_TWI_Configure (AT91C_BASE_TWI);
// Set TWI Clock Waveform Generator Register
AT91F_SetTwiClock(AT91C_BASE_TWI);
}
//*============================================================================
//* 函数名称: AT91F_TWI_Close
//* 函数功能: 关闭 TWI
//*============================================================================
void AT91F_TWI_Close(void)
{
// 禁用 TWI 电源时钟
AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,1 << AT91C_ID_TWI );
}
//*============================================================================
//* 函数名称:AT91F_TWI_Write
//* 函数功能:写 size 字节数据到从设备
//* 入口参数:pTwi :指向TWI结构的首地址-----设为AT91C_BASE_TWI
//* slvAddr : 从设备地址
//* address : 从设备内部地址(要写入数据的位置)
//* *data2send: 要写入数据的起始地址
//* size : 要写入数据的长度
//* 返回值 :0 : 写正常
//* 非0:写过程发生错误
//*============================================================================
int AT91F_TWI_Write(const AT91PS_TWI pTwi ,char slvAddr,int address, char *data2send, int size)
{
unsigned int status,SLV_ADDR,error = 0;
SLV_ADDR = slvAddr << 16;
// 设置 TWI 为主发送模式,内部地址为 1 字节
pTwi->TWI_MMR = ( SLV_ADDR | AT91C_TWI_IADRSZ_1_BYTE ) & ~AT91C_TWI_MREAD;
// 装载从器件内部地址
pTwi->TWI_IADR = address;
status = pTwi->TWI_SR;
pTwi->TWI_THR = *(data2send++);
//delay_ms();
pTwi->TWI_CR = AT91C_TWI_START;
while (size-- >1)
{
// 等待发送保持寄存器空
while (!(pTwi->TWI_SR & AT91C_TWI_TXRDY))
{
// 读取状态寄存器
status = pTwi->TWI_SR;
// 如果发送完一个字节后没收到应答信号,则表明有一次传输错误
if ((status & ERROR) == ERROR)
error++;
}
// 发送下一个字节
pTwi->TWI_THR = *(data2send++);
//delay_ms();
}
// 发送停止位
pTwi->TWI_CR = AT91C_TWI_STOP;
status = pTwi->TWI_SR;
if ((status & ERROR) == ERROR)
error++;
// 等待数据发送完毕
while (!(pTwi->TWI_SR & AT91C_TWI_TXCOMP))
{
status = pTwi->TWI_SR;
if ((status & ERROR) == ERROR)
error++;
}
return error;
}
//*============================================================================
//* 函数名称:AT91F_TWI_Read
//* 函数功能:从从设备中读取 size 字节数据
//* 入口参数:pTwi :指向TWI结构的首地址-----设为AT91C_BASE_TWI
//* slvAddr : 从设备地址
//* address : 从设备内部地址(要读取数据的位置)
//* *data : 要读取数据的起始地址
//* size : 要读取数据的长度
//* 返回值 :0 : 读正常
//* 非0:读过程发生错误
//*============================================================================
int AT91F_TWI_Read(const AT91PS_TWI pTwi ,char slvAddr, int address, char *data, int size)
{
unsigned int status,SLV_ADDR,error;
SLV_ADDR = slvAddr << 16;
// 设置 TWI 为主接收模式,内部地址为 1 字节
pTwi->TWI_MMR = SLV_ADDR | AT91C_TWI_IADRSZ_1_BYTE | AT91C_TWI_MREAD;
// 装载从设备地址
pTwi->TWI_IADR = address;
// 发送起始位
pTwi->TWI_CR = AT91C_TWI_START;
status = pTwi->TWI_SR;
while (size-- >1)
{
// 等待接收保存寄存器满
while (!(pTwi->TWI_SR & AT91C_TWI_RXRDY))
{
// 读取状态寄存器
status = pTwi->TWI_SR;
// 如果发送完一个字节后没收到应答信号,则表明有一次传输错误
if ((status & ERROR) == ERROR)
error++;
}
// 接收数据
*(data++) = pTwi->TWI_RHR;
}
// 发送停止位
pTwi->TWI_CR = AT91C_TWI_STOP;
status = pTwi->TWI_SR;
if ((status & ERROR) == ERROR)
error++;
// 等待数据传输完毕
while (!(pTwi->TWI_SR & AT91C_TWI_TXCOMP))
{
status = pTwi->TWI_SR;
if ((status & ERROR) == ERROR)
error++;
}
// 接收最后一字节
*data = pTwi->TWI_RHR;
return error;
}
//*============================================================================
//* 函数名称:AT24C08_Write_Page
//* 函数功能:写数据到 AT24C08 指定的页面(一次只能写一个页面)
//* 入口参数:page :页面值( AT24C08共4页(0,1,2,3) )
//* address : 写入地址(0~255)
//* *data : 要写入数据的起始地址
//* size : 写入数据的长度
//* 返回值 : 0: 写入数据正常
//* 1: 写入数据时发生错误
//* 2: 页面值范围出错
//* 3: 写入地址范围出错
//* 4: 数据长度范围出错
//* 注:AT24C08 按内部地址递增方式写数据时一次只能写一行(16字节),写入下一行时必须重新指定下一
//* 行地址,否则会以覆盖形式写同一行,但按内部地址递增方式读数据时一次可读多行,原因不明
//*============================================================================
char AT24C08_Write_Page(int page,int address, char *data, int size)
{
unsigned char wordLeng;
char slvAddr,cnt;
if( (page >= AT24C08_PAGE_SIZE)||(page<0) ) // AT24C08 共4页,分别为0,1,2,3, 大于3出错
{
// AT91F_DBGU_Printk("Write AT24C08 page error !\r\n");
return 2;
}
if( (address >= 256)||(address<0) ) // AT24C08 每页只能写256字节,页内地址范围为(0~255)
{
// AT91F_DBGU_Printk("Write AT24C08 address error !\r\n");
return 3;
}
if( (size > (256-address))||(size<0) ) // AT24C08 每页只能写 256 字节
{
// AT91F_DBGU_Printk("Write AT24C08 word leng error !\r\n");
return 4;
}
slvAddr = AT24C08_BASE_ADDR + page;
wordLeng = address%16;
if((wordLeng + size) < 16) // 要写的字节长度不足一行(16字节)
{
AT91F_TWI_Write(AT91C_BASE_TWI, slvAddr, address, data, size);
return 0;
}
else
{
AT91F_TWI_Write(AT91C_BASE_TWI, slvAddr, address, data, (16-wordLeng));
size -= (16-wordLeng);
address += (16-wordLeng); // 要完第一行,换行再写
cnt = (16-wordLeng);
delay_ms(10); // 不延时写数据会出错,原因不明
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -