当前位置:首页 > 单片机 > 单片机
[导读]/************************************************** EEPROM读写操作 晶振:内部 8M***************************************************/#include#include#define uchar unsigned char#define uint unsigned int

/**************************************************
EEPROM读写操作
晶振:内部 8M
***************************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar syserr;
void delay_EEPROM(uchar n) //延时
{
unsigned int a,b;
for(a=0;a for(b=0;b<100;b++)
;
}
//------在此设定芯片型号------
#define e2prom 256// <---在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512

#if e2prom==1
#define PAGE_SIZE 8
#define SIZE 0x007f
#elif e2prom==2
#define PAGE_SIZE 8
#define SIZE 0x00ff
#elif e2prom==4
#define PAGE_SIZE 16
#define SIZE 0x01ff
#elif e2prom==8
#define PAGE_SIZE 16
#define SIZE 0x03ff
#elif e2prom==16
#define PAGE_SIZE 16
#define SIZE 0x07ff
#elif e2prom==32
#define PAGE_SIZE 32
#define SIZE 0x0fff
#elif e2prom==64
#define PAGE_SIZE 32
#define SIZE 0x1fff
#elif e2prom==128
#define PAGE_SIZE 64
#define SIZE 0x3fff
#elif e2prom==256
#define PAGE_SIZE 64
#define SIZE 0x7fff
#elif e2prom==512
#define PAGE_SIZE 128
#define SIZE 0xffff
#endif
//--------------------------

//--------在此设定芯片地址-------
#define W_ADD_COM 0xa0//写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
#define R_ADD_COM 0xa1//读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1
//-------------------------------

#define SLAW0x18//SLA_W 已正常发送代码,判断器件是否正常应答的常量.

//-----在此改变预置错误号-----
#define ERR_SLAW10//写字节命令及器件地址错, 在此也就是读写器件错!!
//---------------------------

//-----------4个I2总线公用函数, 可供其它I2总线器件的程序调用--------------
void i2cstart(void);//总线上起动开始条件
uchar i2cwt(uchar a);//把一个字节数据输入器件, 返回TWI状态
uchar i2crd(void);//i2c读要调用的函数
void i2cstop(void);//总线上起动停止条件
//------------------------------------------------------------------------

uchar * wt24c_fc(uchar *p, uint ad, uchar n);//向24Cxx写入数据wt24c_h()所要调用的函数

//向24Cxx写入数据
//参数: *p_rsc要输出数据的主机内存地址指针; ad_dst要写入数据的i2c的地址(双字节); num数据个数
//参数条件: ad_dst: ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
void wt24c(uchar *p_rsc, uint ad_dst, uint num)
{ uint n;

n=ad_dst/PAGE_SIZE;//确定地址与块地址的差
if(n)
n=(ulong)PAGE_SIZE*(n+1)-ad_dst;
else
n=PAGE_SIZE-ad_dst;

if(n>=num)//如果ad_dst所在的数据块的末尾地址 >= ad_dst + num, 就直接写入num个数据
{
wt24c_fc(p_rsc, ad_dst, num);
if(syserr!=0)
return;
}
else//如果ad_dst所在的数据块末尾地址 < ad_dst + num, 就先写入ad_dst所在的数据块末尾地址与 ad_dst 之差个数据
{
p_rsc=wt24c_fc(p_rsc, ad_dst, n);
if(syserr!=0)
return;

num-=n; //更新剩下数据个数
ad_dst+=n;//更新剩下数据的起始地址

//把剩下数据写入器件
while(num>=PAGE_SIZE)//先按PAGE_SIZE为长度一页一页的写入
{p_rsc=wt24c_fc(p_rsc, ad_dst, PAGE_SIZE);
if(syserr!=0) return;

num-=PAGE_SIZE;//更新剩余数据个数
ad_dst+=PAGE_SIZE;//更新剩下数据的起始地址
}

if(num)//把最后剩下的小于一个PAGE_SIZE长度的数据写入器件
wt24c_fc(p_rsc, ad_dst, num);
}
}


//从24cxx读出数据
//参数: *p_dst要读入数据的主机内存地址指针; ad_rsc要输出数据的i2c的地址(整形); num数据个数(整形)
//参数条件: ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
void port_init(void)
{

PORTC = 0xFF;
DDRC &= 0xfc;
}
//TWI initialize
// bit rate:100
void twi_init(void)
{
TWCR= 0x00; //disable twi
TWBR= 0x20; //set bit rate
TWSR= 0x00; //set prescale
TWAR= 0x00; //set slave address
TWCR= 0x04; //enable twi
}
void rd24c(uchar *p_dst, uint ad_rsc, uint num)
{
uchar t=0;
#if e2prom<32
t=ad_rsc>>8;
t<<=1;
#endif
i2cstart();//发送起始信号
if(i2cwt(W_ADD_COM+t)==SLAW)//发送SLA_W, 写字节命令及器件地址
{
#if e2prom>=32
i2cwt(ad_rsc>>8);//ad_rsc的高位, 发送要读出数据的地址
#endif
i2cwt(ad_rsc);//ad_rsc的低位

i2cstart();//再发送起始信号
i2cwt(R_ADD_COM+t);//发送SLA_R, 读命令字节及器件地址

for(;num>0;num--)
{
*p_dst=i2crd();//从器件读出一个字节
p_dst++;
}
}
else
syserr=ERR_SLAW;//写字节命令及器件地址错或对方无应答

i2cstop();

}
//向24Cxx写入数据wt24c_h()所要调用的函数
//返回写入n个字节后的主机内存指针

uchar * wt24c_fc(uchar *p, uint ad, uchar n)
{
uchar t=0;
#if e2prom<32
t=ad>>8;
t<<=1;
#endif
i2cstart();//发送起始信号
if(i2cwt(W_ADD_COM+t)==SLAW)//发送SLA_W, 写字节命令及器件地址
{
#if e2prom>=32
i2cwt(ad>>8);//ad_dst的高位到器件
#endif
i2cwt(ad);//ad_dst的低位到器件

for(;n>0;n--)//发送要写入的数据
{ i2cwt(*p);
p++;
}
}
else syserr=ERR_SLAW;//写字节命令及器件地址错

i2cstop();
delay_EEPROM(10);//延时6ms

return(p);
}

//-------------------------------以下为其它I2总线器件可调用的函数--------------------------

//总线上起动开始条件
void i2cstart(void)
{
TWCR= BIT(TWINT) | BIT(TWSTA) | BIT(TWEN);
while (!(TWCR & BIT(TWINT)));
}

//把一个字节数据输入器件, 返回TWI状态
uchar i2cwt(uchar a)
{
TWDR = a;
TWCR = BIT(TWINT) | BIT(TWEN);
while (!(TWCR & BIT(TWINT)));
_NOP();
return(TWSR&0b11111000);
}

//i2c读要调用的函数
//从器件读出一个字节
uchar i2crd(void)
{
TWCR= BIT(TWINT) | BIT(TWEA) | BIT(TWEN);
while (!(TWCR & BIT(TWINT)));
return(TWDR);

}


//总线上起动停止条件
void i2cstop(void)
{
TWCR = BIT(TWINT) | BIT(TWSTO) | BIT(TWEN);
}


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

1)那就是在之前的介绍中说过,在说一遍~~主机和从机的两个移位寄存器可以被认为是一个公开的16位环形移位寄存器,当数据从主机移向从机时,同时从机饿数据也向相反的放向移向主机。这就意味着在一个以为周期内,主机

关键字: atmega16 avr单片机 spi 同步串行接口

五、ATMEGA16的USART与PC机串行通信五—(02)、PC机发送字符给单片机,然后用液晶显示发送的字符~~~这章节也是相对挺简单的~~直接上图片吧~~基本上就这么点吧~~然后就是程序了,这里我只是粘贴一下重要的程...

关键字: atmega16 avr单片机 usart 串行通信

九、ATMEGA16的模数转换器九—(01)、ATMEGA16的模数转换器的介绍1、介绍1)特点:? 10 位 精度? 0.5 LSB 的非线性度? ± 2 LSB 的绝对精度? 65 - 260 μs 的转换时间? 最...

关键字: atmega16 avr单片机 模数转换器

五、ATMEGA16的USART与PC机串行通信五—(03)、PC机发送控制指令控制单片机工作~(这个控制还是比较简单的~~,不过个人认为还是有水平的~)还是先上图片~~,然后程序,程序师模块化的,我尽量贴全点~~然后就...

关键字: atmega16 avr单片机 usart 串行通信

三、ATMEGA16驱动16*2点阵字符液晶三—(01)、ATMEGA16驱动16*2点阵字符液晶这篇文章只是简单的驱动并让1602显示,并没有用到读数据和读状态的部分,也没有用到读写检测(要是感兴趣的话还是写写这里吧)...

关键字: atmega16 avr单片机 点阵 字符液晶模块

四、ATMEGA16的定时/计数器四—(01)、四位显示秒表试验首先怀念一下咱们的体育课,再体育课或者田径比赛的时候,老师会经常使用秒表来记录同学们的成绩。在此,来进行一个秒表的设计。(说实话,这个秒表真的太贵了

关键字: atmega16 avr单片机 定时 计数器

//1号主机:#include #include#include#include #defineucharunsigned char#defineSTATUS(TWSR&0xf8)#defineSLA_W0x32...

关键字: atmega16 twi 互相通信 中断形式

在设置之前呢,我得把ATMEGA16里面的datasheet里面的资料说说,当然是关于系统时钟和时钟选项的一、系统时钟及时钟选项(这里主要是介绍原理,三里面会介绍如何设置,其实你会了一,那后面的二和三就相当简单了~~你懂

关键字: atmega16 avr单片机 proteus 系统时钟

//------------------------------------------------------------------------------//ATMEGA16与PC机的通信实验1//PC机发送一个字...

关键字: atmega16 avr单片机 usart 串行通信

一、ATMEGA16的I\\0端口的使用:(只有一个实验,下面的部分每个小节可能有几个实验验证,你懂得)一—(01)、)—使用4*4行列式按键开关的使用I/O端口介绍:直接一个图就哦了,因为根本没什么,就是控制寄存器(这...

关键字: atmega16 avr单片机 i0端口
关闭
关闭