四极管:IIC之AVR 24c64读写

主函数:

四极管:main.c

#include<avr/io.h>
#include<util/delay.h>
#include<1602driver.c>
#include<24c64.c>


int  main(void)
{
	uchar const data[]="0123456789";
	uchar data_from_24c64=0;
    	Init_1602();	
	Write_24c64(0x0000,000);
	_delay_ms(10);
	Displaypstr(0,1,"oh h!");
	DDRA=0Xff;
	PORTA=0X0f;
	data_from_24c64=Read_24c64(0x0000);
	while(1)
	{			
		Displaychar(0,0,data[data_from_24c64/100]);
		Displaychar(1,0,data[(data_from_24c64%100)/10]);
		Displaychar(2,0,data[data_from_24c64%10]);
        		_delay_ms(100);
	}
    	return  0;
}

四极管:24c64驱动(24C64.c)

/***********************************
函数功能:24c64读写操作
          
使用环境:    硬件: MCU: ATmega32L 
                      F_CPU = 16000000
                      外部:16000000 
接线方法:A0/A1/A2接地;WP接地;scl/sda接接10k上拉电阻后接任意两个IO口
          			  
编译环境:WinAVR-20080610	
使用说明:  24c64容量为64kbit  采用线性连续排列,地址空间为0000H-FFFFFH
地址长度为16位  两字节  
            在24c64内部:把64kbit分为2048页,每页32字节,页内偏移量(低五位):0--31(0x00--0x1f)
			页码(高11位):页码:0-2047(0x20---0xffff)
         写操作:
		     1、字节写:(0x00--0x1f)
			 2、页  写:(0x20---0xffff)	  
         读操作:
		     1、字节读:(0x00--0x1f)
			 2、页  读:(0x20---0xffff)	
作者:杨琦  		  
日期:2009年7月26日
修改者: 			   	(日期:  )
 *******************************************************************/
//端口定义   
#define  SDA_1() {DDRB|=(1<<0);PORTB|=(1<<0);}		
#define  SDA_0() {DDRB|=(1<<0);PORTB&=~(1<<0);}
#define  SCL_1() {DDRB|=(1<<1);PORTB|=(1<<1);}		
#define  SCL_0() {DDRB|=(1<<1);PORTB&=~(1<<1);}

#define uint  unsigned int
#define uchar unsigned char
/*---------------IIC总线操作流程-----------------------------------------
*  一、 写操作顺序:
*    启动总线→写器件地址→写单元地址→写数据→. . .→关闭总线
*    器件地址组成:固定地址(厂家)+外部连线地址+1位读写地址(1:读 ,0:写)
*  二、 指定单元读操作:
*    启动总线→写器件地址→写单元地址→启动总线→写入要读出的器件地址→
*    读数据→. . .→关闭总线
*  三、 当前单元读操作
*    启动总线→写入要读出的器件地址→读数据→. . .→关闭总线
------------------------------------------------------------------------*/


/*---------------IIC总线器件地址-----------------------------------------
*  IIC总线地址格式:1010XXXX
*  地址说明:
*        BIT7-BIT4:IIC总线地址高4位固定为1010,即10进制A
*        BIT3-BIT1:地址为生产厂家规定地址,如PCF8563为001,24C系列为000
*        BIT0     :读写控制位,0:写操作;1:读操作          
------------------------------------------------------------------------*/

/****************************************
** 函数名:延时子函数                   *
** 功  能:稍作延时                     *
** 子函数:无                           *
** 变  量:uint time                    *
** 返回值:无                           *
****************************************/
void DelayMS(uint time) 
{ 
  do 
  { 
    time--;  
  } 
  while(time); 
} 

/****************************************
** 函数名:启动器件子程序               *
** 功  能:I2C启动总线                  *
** 子函数:DelayMs();                   *
** 变  量:无                           *
** 返回值:无                           *
****************************************/
void  Start_24c64(void)
{
	SDA_1();
	DelayMS(2); 
	SCL_1();
	DelayMS(2);
	SDA_0();
	DelayMS(8);
	SCL_0(); 
	DelayMS(2); 
}	
/****************************************
** 函数名:停止器件子程序               *
** 功  能:I2C启动总线                  *
** 子函数:DelayMs();                   *
** 变  量:无                           *
** 返回值:无                           *
****************************************/
void Stop_24c64(void)
{
    SDA_0();
	DelayMS(2);
	SCL_0();
	DelayMS(2);
	SCL_1();
	DelayMS(2);
	SDA_1();
	DelayMS(8);
	SCL_0();
	DelayMS(2);
}

/*********************************************
** 函数名:主机发送一个字节数据至24c64子程序 *
** 功  能:向24c64写一个字节,从高位开始     *
** 子函数:DelayMs();                        *
** 变  量:uchar bytedata                    *
** 返回值:uchar                             *
**********************************************/
uchar SendByte_24c64(uchar bytedata)
{
    uchar i;
	uchar flag=0;
	SCL_0();
	DelayMS(4);
	for(i=0;i<8;i++)
	{
		if(bytedata&0x80) 
		{
		    SDA_1();
		}	
		else              
		{
		    SDA_0();
		}	
		DelayMS(2);
		SCL_1();
		DelayMS(2);
		bytedata<<=1;
		SCL_0();
		DelayMS(2);
	}
	SDA_1();
	DelayMS(2);
	DDRB&=~(1<<0);
	SCL_1();	
	DelayMS(1);
	if(!(PINB&(1<<0)))
	{
		flag=1;
	}
	DDRB|=(1<<0);	
	SCL_0();
	DelayMS(2);
	return(flag);
	
}
/*********************************************
** 函数名:主机接收一个字节子程序从高位开始读*
** 功  能:读取24c64一个字节,从高位开始读    *
** 子函数:DelayMs();                        *
** 变  量:uchar ack                         *
** 返回值:uchar                             *
**********************************************/
uchar ReceiveByte_24c64(uchar ack)
{
    uchar i,a=0;
	SCL_0();
	for(i=0;i<8;i++)
	{
		SDA_1();
		DelayMS(2);
	    a<<=1;
		DDRB&=~(1<<0);
		SCL_1();
		DelayMS(2);
		if(PINB&(1<<0)) 
		{
		    a++;
		}
		SCL_0();
		DelayMS(2);
	}	
	DDRB|=(1<<0);
	if(!ack)
	{
		SDA_1();
	}
	else
	{
		SDA_0();
	}
	SCL_1();
	DelayMS(2);
	SCL_0();
	DelayMS(2);
	return(a);	 
		 
} 

/*********************************************************
** 函数名:向24c64写如数据                               *
** 功  能:向24c64写入其地址和数据                       *
** 子函数:Start_24c64();SendByte_24c64();Stop_24c64();  *
** 变  量:uint Address, uchar Data                      *
** 返回值:无                                            *
*********************************************************/

void Write_24c64(uint Address, uchar Data)
{ 
  uchar flag1=0,flag2=0,flag3=0,flag4=0;  
  Start_24c64();   //启动总线
  flag1=SendByte_24c64(0xa0);  //写器件地址 确保最低位(w/R)位为0
  DelayMS(5);
  if(flag1==1)
  {                                                                                                          
    flag2=SendByte_24c64((Address&0xff00)>>8);//写单元地址高位
	DelayMS(5);
	if(flag2==1)
	{
	   flag3=SendByte_24c64(Address&0xff);//写单元地址低位
	   DelayMS(5);
		if(flag3==1)
		{
			flag4=SendByte_24c64(Data); //写数据
			DelayMS(5);
		}
	}   
  }
    Stop_24c64();    //停止总线
}
/**************************************************************************
** 函数名:从24c64读取数据                                                *
** 功  能:向24c64指定地址读取数据                                        *
** 子函数:Start_24c64();SendByte_24c64();ReceiveByte_24c64Stop_24c64();  *
** 变  量:uint Address                                                   *
** 返回值:uchar                                                          *
***************************************************************************/
 uchar Read_24c64(uint Address) //分为立即读和选择读
 {   

   uchar flag1=0,flag2=0,flag3=0,flag4=0;
	uchar readdata=0;
	Start_24c64();     // 开启总线
	flag1=SendByte_24c64(0xa0);  //写器件地址(写操作)
	DelayMS(5);
	if(flag1==1)
	{
		flag2=SendByte_24c64((Address&0xff00)>>8);//写单元地址高位
		DelayMS(5);
		if(flag2==1)
		{
			flag3=SendByte_24c64(Address&0xff);//写单元地址低位
			DelayMS(5);
			if(flag3==1)
			{
				Start_24c64();    //启动总线
				flag4=SendByte_24c64(0xa1);   //写器件地址(读操作)
				DelayMS(5);
				if(flag4==1)
				{  
				   
					readdata=ReceiveByte_24c64(1);    //读数据
					DelayMS(5);
				}
			}
		}
	}
	Stop_24c64();
	return(readdata);	
}

四极管:液晶显示驱动(1602driver.c)

/***********************************
 函数功能:1602 液晶显示两行数字和字符
 函数说明:四线方式,数据输出线:DATA_PORT
          
 使用环境:    硬件: MCU: ATmega32L 
                      F_CPU = 16000000
                      外部:16000000 
 接线方法:3跟数据线:PC1-RS   PC2-RW  PC3-E
           4跟数据线:PC				  
 编译环境:WinAVR-20080610	
 显示说明:  
         显示字符函数:
             Displaychar(unsigned char x,unsigned char y, unsigned char wdata)
            (x为横坐标   y为坐标 wdata为所要显示的东西)
		 显示字符串函数:
		     Displaypstr(unsigned char x,unsigned char y,unsigned char *str)
            (x为横坐标   y为坐标  wdata为所要显示的东西)
		  
 坐标定位说明:X:0-15
                Y:0-1	
 包含文件 :MyBit.h 	
 作者:杨琦			  
 日期:2009年7月13日
 修改者: 			   	(日期:  )				   
***********************************/		  
//管脚定义		  
#define DATA_PORT PORTC
#define RS_0() {DDRC |=(1<<1);PORTC &=~(1<<1);}       
#define RS_1() {DDRC |=(1<<1);PORTC |= (1<<1);}
#define RW_0() {DDRC |=(1<<2);PORTC &=~(1<<2);}
#define RW_1() {DDRC |=(1<<2);PORTC |= (1<<2);}
#define E_0()  {DDRC |=(1<<3);PORTC &=~(1<<3);} 
#define E_1()  {DDRC |=(1<<3);PORTC |= (1<<3);} 


#define budy_in()   {DDRC&=~(1<<7);PORTC|=(1<<7);}
#define budy_high    PINC&(1<<7)
#define busy_out()   {DDRC|=(1<<7);}
//注:读忙函数需对输出口最高位进行设置和判断
/****************************************
** 函数名:readbusy
** 功能  :读忙函数
** 子函数:无
** 变量  :无
----------------------------------------
****************************************/
void readbusy(void)
{
	 //检测忙位改为输入
	budy_in();//拉高
    RW_1();
	RS_0();
	E_1();
	while(budy_high);//等待为低电平   ????????@@@@@@
	E_0();
	busy_out(); 
}
/****************************************
** 函数名:sentbyte
** 功能  :发送一节数
** 子函数:readbusy()
** 变量  :数据或命令 tybe=1数据 0命令
----------------------------------------
****************************************/
void sentbyte(unsigned char i,unsigned char tybe)
{
    unsigned char temp;
	readbusy();
	
    if(tybe == 1)
	{
	    RW_0();
        RS_1();	
    }
	if(tybe == 0)
	{
	    RW_0();
		RS_0();
	}
	
	temp = i&0xf0;
	DATA_PORT &=0x0f;
    DATA_PORT |=temp;
    E_1();
    E_0(); 
	
	temp = (i<<4)&0xf0;
	DATA_PORT &=0X0f;
	DATA_PORT |=temp;
	E_1();
    E_0(); 
}
/****************************************
** 函数名:Init_1602()
** 功能  :初始化1602液晶显示
** 变量  :无
----------------------------------------
****************************************/
void Init_1602(void)
{
    DDRC = 0xff;
	
    sentbyte(0x30,0);
    sentbyte(0x30,0);
	sentbyte(0x30,0);
	sentbyte(0x02,0);

    sentbyte(0x28,0);   //设置工作方式:4位总线字符两行0x28,8位总线字符两行0x38
	sentbyte(0x01,0);  //清屏
	sentbyte(0x02,0);   //数据指针清零
	sentbyte(0x0c,0);   //开光标,但光标不闪
	sentbyte(0x06,0);   //写字符后光标加一
	sentbyte(0x01,0);   //清屏
}
/****************************************
** 函数名:Locate_xy()
** 功能  :写地址
** 变量  :x,y
----------------------------------------
****************************************/
void Locate_xy(unsigned char x,unsigned char y )
{
    unsigned char addr=0;
	if(y == 0)addr=0x80+x;
	if(y == 1)addr=0xc0+x;
    sentbyte(addr,0);
}

/****************************************
** 函数名:Displaychar()
** 功能  :1602液晶显示一个字符
** 变量  :x,y,wdata
----------------------------------------
****************************************/
void Displaychar(unsigned char x,unsigned char y,
    unsigned char wdata)
{
    Locate_xy(x,y);   
    sentbyte(wdata,1);
}
/****************************************
** 函数名:Displaypstr()
** 功能  :1602液晶显示一个字符串
** 变量  :x,y,*str
----------------------------------------
****************************************/
void Displaypstr(unsigned char x,unsigned char y,unsigned char *str)
{
    unsigned int i=0;
	Locate_xy(x,y);   
	while(str[i]!='\0')
	{
	    sentbyte(str[i++],1);
	    x++;
	    if(x>15)
	    {
		   x=0;
		   y++;
		   if(y==2)y=0;
		   Locate_xy(x,y);   
		}
	}    
}

头文件定义(MyBit.h)

/***********************************************************  文件名称:位操作头文件  File :MyBit.h  功能描述:通过位段定义的方法,把位从字节中分离成  位变量,即可对端口或一般寄存器进行位操作  使用范例:    A口0脚输出高电平: OA0=1;    读取A口1脚电平: while(IA1);    设置A口2脚为输出: RA2=1;  创建日期:2007-2-14  Author :廖志贤 ***********************************************************/

typedef struct { unsigned  bit0: 1 ; unsigned  bit1: 1 ; unsigned  bit2: 1 ; unsigned  bit3: 1 ; unsigned  bit4: 1 ; unsigned  bit5: 1 ; unsigned  bit6: 1 ; unsigned  bit7: 1 ; }PORTtype,Byte;

typedef struct { unsigned  bit0: 1 ; unsigned  bit1: 1 ; unsigned  bit2: 1 ; unsigned  bit3: 1 ; unsigned  bit4: 1 ; unsigned  bit5: 1 ; unsigned  bit6: 1 ; unsigned  bit7: 1 ; unsigned  bit8: 1 ; unsigned  bit9: 1 ; unsigned  bit10: 1 ; unsigned  bit11: 1 ; unsigned  bit12: 1 ; unsigned  bit13: 1 ; unsigned  bit14: 1 ; unsigned  bit15: 1 ; }Word; /************************************************* IO位定义开始 *************************************************/

//************************************************

//定义A口端口数据寄存器,等同于PORTA #define A_OUT (*(volatile PORTtype *)(0x1B+0x20)) //定义A口端口方向寄存器,等同于DDRA #define A_DIR (*(volatile PORTtype *)(0x1A+0x20)) //定义A口端口输入寄存器,等同于PINA #define A_DIN (*(volatile PORTtype *)(0x19+0x20))

//定义B口端口数据寄存器,等同于PORTB #define B_OUT (*(volatile PORTtype *)(0x18+0x20)) //定义B口端口方向寄存器,等同于DDRB #define B_DIR (*(volatile PORTtype *)(0x17+0x20)) //定义B口端口输入寄存器,等同于PINB #define B_DIN (*(volatile PORTtype *)(0x16+0x20))

//定义C口端口数据寄存器,等同于PORTC #define C_OUT (*(volatile PORTtype *)(0x15+0x20)) //定义C口端口方向寄存器,等同于DDRC #define C_DIR (*(volatile PORTtype *)(0x14+0x20)) //定义C口端口输入寄存器,等同于PINC #define C_DIN (*(volatile PORTtype *)(0x13+0x20))

//定义D口端口数据寄存器,等同于PORTD #define D_OUT (*(volatile PORTtype *)(0x12+0x20)) //定义D口端口方向寄存器,等同于DDRD #define D_DIR (*(volatile PORTtype *)(0x11+0x20)) //定义D口端口输入寄存器,等同于PIND #define D_DIN (*(volatile PORTtype *)(0x10+0x20))

//************************************************

//预定义口位OAX----大写字母O表示output,表明 //这种表示对应PORTA的使用方法,即输出寄存器,以 //数字X为第X位 //下OBX,OCX,ODX为相同意义

//预定义口位RAX----大写字母R表示rudder(方向舵), //表明这种表示对应DDRA的使用方法,即用于设置端 //口方向,以下RBX,RCX,RDX为相同意义

//预定义口位IAX----大写字母I表示input,表明 //这种表示对应PINA的使用方法,即读取端口电平, //以下IBX,ICX,IDX为相同意义

//-----------------------************************ //输出数据

#define OA0 A_OUT.bit0 #define OA1 A_OUT.bit1 #define OA2 A_OUT.bit2 #define OA3 A_OUT.bit3 #define OA4 A_OUT.bit4 #define OA5 A_OUT.bit5 #define OA6 A_OUT.bit6 #define OA7 A_OUT.bit7

#define OB0 B_OUT.bit0 #define OB1 B_OUT.bit1 #define OB2 B_OUT.bit2 #define OB3 B_OUT.bit3 #define OB4 B_OUT.bit4 #define OB5 B_OUT.bit5 #define OB6 B_OUT.bit6 #define OB7 B_OUT.bit7

#define OC0 C_OUT.bit0 #define OC1 C_OUT.bit1 #define OC2 C_OUT.bit2 #define OC3 C_OUT.bit3 #define OC4 C_OUT.bit4 #define OC5 C_OUT.bit5 #define OC6 C_OUT.bit6 #define OC7 C_OUT.bit7

#define OD0 D_OUT.bit0 #define OD1 D_OUT.bit1 #define OD2 D_OUT.bit2 #define OD3 D_OUT.bit3 #define OD4 D_OUT.bit4 #define OD5 D_OUT.bit5 #define OD6 D_OUT.bit6 #define OD7 D_OUT.bit7

//--------------------*************************** //设置方向

#define RA0 A_DIR.bit0 #define RA1 A_DIR.bit1 #define RA2 A_DIR.bit2 #define RA3 A_DIR.bit3 #define RA4 A_DIR.bit4 #define RA5 A_DIR.bit5 #define RA6 A_DIR.bit6 #define RA7 A_DIR.bit7

#define RB0 B_DIR.bit0 #define RB1 B_DIR.bit1 #define RB2 B_DIR.bit2 #define RB3 B_DIR.bit3 #define RB4 B_DIR.bit4 #define RB5 B_DIR.bit5 #define RB6 B_DIR.bit6 #define RB7 B_DIR.bit7

#define RC0 C_DIR.bit0 #define RC1 C_DIR.bit1 #define RC2 C_DIR.bit2 #define RC3 C_DIR.bit3 #define RC4 C_DIR.bit4 #define RC5 C_DIR.bit5 #define RC6 C_DIR.bit6 #define RC7 C_DIR.bit7

#define RD0 D_DIR.bit0 #define RD1 D_DIR.bit1 #define RD2 D_DIR.bit2 #define RD3 D_DIR.bit3 #define RD4 D_DIR.bit4 #define RD5 D_DIR.bit5 #define RD6 D_DIR.bit6 #define RD7 D_DIR.bit7

//----------------------************************** //读取端口

#define IA0 A_DIN.bit0 #define IA1 A_DIN.bit1 #define IA2 A_DIN.bit2 #define IA3 A_DIN.bit3 #define IA4 A_DIN.bit4 #define IA5 A_DIN.bit5 #define IA6 A_DIN.bit6 #define IA7 A_DIN.bit7

#define IB0 B_DIN.bit0 #define IB1 B_DIN.bit1 #define IB2 B_DIN.bit2 #define IB3 B_DIN.bit3 #define IB4 B_DIN.bit4 #define IB5 B_DIN.bit5 #define IB6 B_DIN.bit6 #define IB7 B_DIN.bit7

#define IC0 C_DIN.bit0 #define IC1 C_DIN.bit1 #define IC2 C_DIN.bit2 #define IC3 C_DIN.bit3 #define IC4 C_DIN.bit4 #define IC5 C_DIN.bit5 #define IC6 C_DIN.bit6 #define IC7 C_DIN.bit7

#define ID0 D_DIN.bit0 #define ID1 D_DIN.bit1 #define ID2 D_DIN.bit2 #define ID3 D_DIN.bit3 #define ID4 D_DIN.bit4 #define ID5 D_DIN.bit5 #define ID6 D_DIN.bit6 #define ID7 D_DIN.bit7

 

 

 

 

 

转载请注明出处。作者:四极管。广西师范大学 电子工程学院大学生科技创新基地 邮箱: yangxingbo-0311@163.com



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值