利用AVR片内IIC 实现AT24C256 的连续写(页写)与连续读程序

发布者:SparkleMagic最新更新时间:2017-11-24 来源: eefocus关键字:AVR  片内IIC  AT24C256 手机看文章 扫描二维码
随时随地手机看文章

最近刚买回一块AT24C256 EEPROM ,容量为32K Byte ,数据地址宽度为 16Bit ,支持IIC 1M (5V)400K (2.7V) 速度模式 ,利用AVR M16 片内IIC 可以高速稳定地读取数据…… 爽! 经过调试的,与各位大虾分享分享。




程序如下:(winavr)

#include
#include
#include
#include
#define FREQ 8
#include
#include
#include

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//管脚定义
#define pinSCL    0     //PC0 SCL
#define pinSDA    1     //PC1 SDA
//为保险起见,最好在SCL/SDA接上1~10K的外部上拉电阻到VCC。

#define fSCL    1000000    //TWI时钟为1000KHz
//预分频系数=1(TWPS=0)
#if F_CPU < fSCL*36
#define TWBR_SET    2;     //TWBR必须大于等于10
#else
#define TWBR_SET    (F_CPU/fSCL-16)/2; //计算TWBR值
#endif

#define TW_ACT    (1<//TWCR只能IN/OUT,直接赋值比逻辑运算(|= &=)更节省空间

#define SLA_24CXX   0xA0    //24Cxx系列的厂商器件地址(高四位)
#define ADDR_24C256   0x00
// AT24C256的地址线A2/1/0全部接地,SLAW=0xA0+0x00<<1+0x00,SLAR=0xA0+0x00<<1+0x01

//TWI_操作状态
#define TW_BUSY    0
#define TW_OK    1
#define TW_FAIL    2
//TWI_读写命令状态
#define OP_BUSY    0
#define OP_RUN    1


//TWI读写操作公共步骤
#define ST_FAIL    0 //出错状态
#define ST_START   1 //START状态检查
#define ST_SLAW    2 //SLAW状态检查
#define ST_WADDR_H   3 //ADDR状态检查
#define ST_WADDR_L   4 //ADDR状态检查
//TWI读操作步骤
#define ST_RESTART   5 //RESTART状态检查
#define ST_SLAR    6 //SLAR状态检查
#define ST_RDATA   7 //读取数据状态检查,循环n字节
//TWI写操作步骤
#define ST_WDATA   8 //写数据状态检查,循环n字节

#define FAIL_MAX   1 //重试次数最大值

void delay_nms(uint ms)//若干毫秒延时
{
int i;
for(i=0;i{
   _delay_loop_2(FREQ*250);
}
}

unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len);

unsigned char BUFFER[256];      //缓冲区
void Test(void);

struct str_TWI         //TWI数据结构
{
    volatile unsigned char STATUS;    //TWI_操作状态
    unsigned char SLA;      //从设备的器件地址
    unsigned char ADDR_H;      //从设备的数据地址
unsigned char ADDR_L;      //从设备的数据地址
    unsigned char *pBUF;      //数据缓冲区指针
    unsigned int DATALEN;     //数据长度
    unsigned char STATE;      //TWI读写操作步骤
    unsigned char FAILCNT;     //失败重试次数
};

struct str_TWI strTWI;       //TWI的数据结构变量

//AT24C256的读写函数(包括随机读,连续读,字节写,页写)
//根据sla的最低位决定(由中断程序中判断)
//bit0=1 TW_READ 读
//bit0=0 TW_WRITE 写
// sla   器件地址(不能搞错)
// addr EEPROM地址(0~32767)
// *ptr 读写数据缓冲区
// len   读数据长度(1~32768),写数据长度(1 or 8 or 16 or 32 or 64)
// 返回值 是否能执行当前操作
unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len)
{
   // unsigned char i;
    if (strTWI.STATUS==TW_BUSY)
    {//TWI忙,不能进行操作
        return OP_BUSY;
    }
    strTWI.STATUS=TW_BUSY;
    strTWI.SLA=sla;
    strTWI.ADDR_H=(unsigned char)((addr>>8)&0xff);
strTWI.ADDR_L=(unsigned char)(addr&0xff);
    strTWI.pBUF=ptr;
    strTWI.DATALEN=len;
    strTWI.STATE=ST_START;
    strTWI.FAILCNT=0;
    TWCR=(1<    return OP_RUN;
}

SIGNAL(SIG_2WIRE_SERIAL)
{//IIC中断
    unsigned char action,state,status;
    action=strTWI.SLA&TW_READ;     //取操作模式
    state=strTWI.STATE;
    status=TWSR&0xF8;       //屏蔽预分频位
    if ((status>=0x60)||(status==0x00))
    {//总线错误或从机模式引发的中断,不予处理
        return;
    }
    switch(state)
    {
    case ST_START: //START状态检查
        if(status==TW_START)
        {//发送start信号成功
            TWDR=strTWI.SLA&0xFE;    //发送器件地址写SLAW
            TWCR=TW_ACT;             //触发下一步动作,同时清start发送标志
        }
        else
        {//发送start信号出错
            state=ST_FAIL;
        }
        break;
    case ST_SLAW: //SLAW状态检查
        if(status==TW_MT_SLA_ACK)
        {//发送器件高位地址成功
            TWDR=strTWI.ADDR_H;     //发送eeprom地址
            TWCR=TW_ACT;             //触发下一步动作
        }
        else
        {//发送器件地址出错
            state=ST_FAIL;
        }
        break;
    case ST_WADDR_H: //ADDR状态检查
        if(status==TW_MT_DATA_ACK)
        {//发送器件低位地址成功
            TWDR=strTWI.ADDR_L;     //发送eeprom地址
            TWCR=TW_ACT;             //触发下一步动作
        }
        else
        {//发送器件地址出错
            state=ST_FAIL;
        }
        break;
    case ST_WADDR_L: //ADDR状态检查
        if(status==TW_MT_DATA_ACK)
        {//发送eeprom地址成功
            if (action==TW_READ)
            {//读操作模式
                TWCR=(1<            }
            else
            {//写操作模式
                TWDR=*strTWI.pBUF++;          //写第一个字节
                strTWI.DATALEN--;
                state=ST_WDATA-1;    //下一步将跳到WDATA分支
                TWCR=TW_ACT;            //触发下一步动作
            }
        }
        else
        {//发送eeprom地址出错
            state=ST_FAIL;
        }
        break;
    case ST_RESTART: //RESTART状态检查,只有读操作模式才能跳到这里
        if(status==TW_REP_START)
        {//发送restart信号成功
            TWDR=strTWI.SLA;     //发器件地址读SLAR
            TWCR=TW_ACT;             //触发下一步动作,同时清start发送标志
        }
        else
        {//重发start信号出错
            state=ST_FAIL;
        }
        break;
    case ST_SLAR: //SLAR状态检查,只有读操作模式才能跳到这里
        if(status==TW_MR_SLA_ACK)
        {//发送器件地址成功
            if (strTWI.DATALEN--)
            {//多个数据
                TWCR=(1<            }
            else
            {//只有一个数据
                TWCR=TW_ACT;     //设定NAK,触发下一步动作
            }
        }
        else
        {//发送器件地址出错
            state=ST_FAIL;
        }
        break;
    case ST_RDATA: //读取数据状态检查,只有读操作模式才能跳到这里
        state--;        //循环,直到读完指定长度数据
        if(status==TW_MR_DATA_ACK)
        {//读取数据成功,但不是最后一个数据
            *strTWI.pBUF++=TWDR;
            if (strTWI.DATALEN--)
            {//还有多个数据
                TWCR=(1<            }
            else
            {//准备读最后一个数据
                TWCR=TW_ACT;     //设定NAK,触发下一步动作
            }
        }
        else if(status==TW_MR_DATA_NACK)
        {//已经读完最后一个数据
            *strTWI.pBUF++=TWDR;
            TWCR=(1<            strTWI.STATUS=TW_OK;
        }
        else
        {//读取数据出错
            state=ST_FAIL;
        }
        break;
    case ST_WDATA: //写数据状态检查,只有写操作模式才能跳到这里
        state--;        //循环,直到写完指定长度数据
        if(status==TW_MT_DATA_ACK)
        {//写数据成功
            if (strTWI.DATALEN)
            {//还要写
                TWDR=*strTWI.pBUF++;
                strTWI.DATALEN--;
                TWCR=TW_ACT;            //触发下一步动作
            }
            else
            {//写够了
                TWCR=(1<                strTWI.STATUS=TW_OK;
                //启动写命令后需要10ms(最大)的编程时间才能真正的把数据记录下来
                //编程期间器件不响应任何命令
            }
        }
        else
        {//写数据失败
            state=ST_FAIL;
        }
        break;
    default:
        //错误状态
        state=ST_FAIL;
        break;
    }

    if (state==ST_FAIL)
    {//错误处理
        strTWI.FAILCNT++;
        if (strTWI.FAILCNT        {//重试次数未超出最大值,
            TWCR=(1<        }
        else
        {//否则停止
            TWCR=(1<            strTWI.STATUS=TW_FAIL;
        }
    }
    state++;
    strTWI.STATE=state;       //保存状态
}





int main(void)
{
wdt_disable();
sei();
Uart_Init();
printf("\nStart");
Test();
printf("\nFinish");
while(1);

}


void Test(void)
{

uint i,j,k,z;

for(k=0;k<2;k++)
{
   for(j=0;j<256;j++)
   {
    BUFFER[j]=SystemPIC[j+k*256];
   }
  
   for(i=0;i<4;i++)
   {
    strTWI.STATUS=TW_OK;
    TWI_RW(SLA_24CXX+(ADDR_24C256<<1)+TW_WRITE,i*64+k*256+SystemPIC_address,&BUFFER[i*64],64);
    while(strTWI.STATUS==TW_BUSY);   //等待操作完成
    //如果不加等待,则需要检测返回值i才能知道当前操作是否执行了
    // 0 OP_BUSY 之前的操作没完成,没执行当前操作
    // 1 OP_RUN 当前操作执行中
    if (strTWI.STATUS==TW_FAIL)
     {
      printf("\nFail!\n");//操作失败
     }
        
    delay_nms(100); 
   
       
    } 
  
}


关键字:AVR  片内IIC  AT24C256 引用地址:利用AVR片内IIC 实现AT24C256 的连续写(页写)与连续读程序

上一篇:ICCAVR编程Atmega128规则之计数/定时器T1的使用 溢出中断 定时
下一篇:AVR(Mega8)的 IO口模拟SPI,读写FLASH

推荐阅读最新更新时间:2024-03-16 15:46

如何给AVR16芯片解锁
畅学AVRM16核心板本身集成了强大的芯片自解锁功能模块,当由于熔丝位设置错误,导致芯片锁死,无法正常使用时候,可以利用畅学AVR16核心板上的解锁功能给芯片解锁。 (如果芯片没有锁死,可以跳过此步骤) 解锁步骤: 1) 连接AVR16核心板、USBasp下载器、电脑主机。具体操作为: 用10芯下载线将USB-ASP和开发板的ISP接口相连,用USB线将USB-ASP和主机相连; 2) 给核心板插上12M晶振,把畅学AVR核心板上的J1用跳线帽连接; 3) 打开progisp软件,如下,点击“读出”,信息提示框显示读出成功,熔丝位配置栏中,将显示芯片已错误配置的熔丝位; 4) 读出芯片已配置的熔丝位后,重新
[单片机]
如何给<font color='red'>AVR</font>16芯片解锁
NRF24L01无线模块发送-AVR程序代码
#include #include #include lcd12864.h #define uint unsigned int #define uchar unsigned char #define MISO PINB.6 #define SCK PORTB.7 #define MOSI PORTB.5 #define CSN PORTC.0 #define CE PORTC.1 #define IRQ PORTC.2 #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式 #define EN_AA 0x01//自动应答使能 #define EN_RXADDR 0x02
[单片机]
嵌入式学习笔记21——AVR单片机之片内EEPROM
1. ATmega16单片机内部具有512字节的EEPROM,它是一个独立的数据空间。数据读写以一字节为单位,通过专用的指令来实现对EEPROM的操作,也可通过ISP,JTAG,并行编程的方式实现EEPROM的读写;采用内部RC振荡器的1MHz作为访问的定时时钟,其编程使用周期8848个周期,时间大约8.5ms;操作过程中尽量关闭中断,保证时序不被打断。 2. EEPROM存储器相关的寄存器 程序中可直接对地址寄存器EEAR赋值,如EEAR=0x01BA。 控制寄存器EECR用于控制单片机对EEPROM的操作 位3 EERIE:EEPROM中断准备好使能位。当EERIE置1而且全局中断I置
[单片机]
嵌入式学习笔记21——<font color='red'>AVR</font>单片机之<font color='red'>片内</font>EEPROM
AVR单片机中未用的I/O口设置
如果有引脚未被使用,建议给这些引脚赋予一个确定电平。虽然在深层休眠模式下大多数数字输入被禁用,但还是需要避免因引脚没有确定的电平而造成悬空引脚在其它数字输入使能模式( 复位、工作模式、空闲模式) 消耗电流。 最简单的保证未用引脚具有确定电平的方法是使能内部上拉电阻。但要注意的是复位时 上拉电阻将被禁用。如果复位时的功耗也有严格要求则建议使用外部上拉或下拉电阻。不推荐直接将未用引脚与VCC 或GND 连接,因为这样可能会在引脚偶然作为输出时出现冲击电流。
[单片机]
AVR128的程序——单个LED灯闪烁
#include iom128v.h #define uchar unsigned char #define uint unsigned int void Delayms(uint MS); void main(void) { DDRA=0XFF; PORTA=0XFF; DDRF |=0X08; PORTF|=0X08; DDRB |=0X10; PORTB|=0X10; while(1) { PORTA=0xFE; Delayms(500);
[单片机]
基于AVR与DDS技术的超声波电源研制
1引言 近年来, 随着压电材料、电力电子技术的飞速发展,超声在工业、农业、生物、医药卫生、环境保护等国民经济的各个部门以及国防工业中已得到广泛的应用 。超声技术的两大核心要素包括换能器和超声电源 。目前,超声技术向高频率、高稳定性发展,因此对超声电源的性能提出了更高的要求。在超声系统工作过程中,由于变幅杆系统刚度、载荷、工作面积等因素的变化,导致换能器系统固有频率发生漂移 ,要求超声电源具有精确的频率自动跟踪功能 ,以满足换能器稳定的超声输出。此外,目前对换能器多种工作频率的需求日愈增加,急需具有多种频率选择的超声电源与之配对 。本文采用DDS与AVR,研制了一种新型超声波电源,能够提供500kHz、功率为3.2瓦范围内的电信号输出
[单片机]
基于<font color='red'>AVR</font>与DDS技术的超声波电源研制
AVR单片机熔丝位的设置及拯救方法
AVR单片机需要设置合适的熔丝位才能实现其功能,如果熔丝位设置的不对将有可能导致单片机自锁,这是我整理的AVR单片机熔丝位的设置及拯救方,希望对大家有帮助。
[单片机]
<font color='red'>AVR</font>单片机熔丝位的设置及拯救方法
AVR单片机的RTOS-AVRX应用
引 言   随着技术的发展,嵌入式系统的设计及应用对人们的生活产生了很大的影响,并将逐渐改变人们未来的生活方式。在特定的操作系统上开发应用程序,可以使开发人员忽略掉很多底层硬件细节,使得应用程序调试更方便、易于维护、开发周期缩短并且降低开发成本,因而嵌入式操作系统深得开发人员的青睐。   AVR微处理器是Atmel公司开发的8位嵌入式RISC处理器,它具有高性能、高保密性、低功耗、非易失性等优点,而且程序存储器和数据存储器可独立编址,并具有独立访问的哈佛结构。AVR单片机内核有丰富的指令集,通过32个通用寄存器直接与逻辑运算单元相连接,允许在一个周期内一条单一指令访问两个独立的寄存器,这样的结构使代码的执行效率比传统的复杂指令集
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved