⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 at24x.c

📁 ADS1.2下AT91SAM9260对AT24C08 EEPROM的读写操作
💻 C
📖 第 1 页 / 共 2 页
字号:


#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 + -