TWI读写ZLG7290

    技术2022-05-18  16

    //************TWI初始化*************// void Init_TWI(void) { DDRD&=~(1<<PD2); TWCR= 0x00;                //禁止TWI  TWBR= 38;                  //波特率15   //当电压为5V时, 上拉电阻为10K时, SCL和SDA的一个时钟周期为10us; 上拉电阻为1K时, SCL和SDA的一个时钟周期为2.5us;   //TWBR值需要仔细调节以配合ZLG7290的IIC频率要求   TWSR= 0x00;                //预分频系数1,或(0<<TWPS1)|(0<<TWSP0);  // TWAR= 0xA0;             //IIC从机地址SLAVE=0xa0   TWCR= 0x04;                //使能TWI,禁止中断,即:TWCR =(1<<TWEN),                              //禁止中断即TWINT被清零,TWI立即开始工作,因此,在                              //清零TWINT之前一定要首先完成对地址寄存器TWAR,                              //状态寄存器TWSR,以及数据寄存器TWDR的访问。 }

    void DelayMs(uint i)  //1ms { uint j;   for(;i!=0;i--)    {for(j=4000;j!=0;j--) {;}} }

    /**************************************************** ***************************************************** 向IIC地址为Slave的从机的Address地址发送(写)一字节数据Data           返回0:写成功            返回非0:写失败  ****************************************************** ******************************************************/

    uchar TWI_Send(uchar Slave,uchar Address,uchar Data) {  TWCR=0x80|0x20|0x04;       //或:TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);对TWINT写1清除,使能TWI,发出Start信号  while((TWCR&0x80)!=0x80) ; //或:while (!(TWCR & (1<<TWINT)));等待TWINT置位,表明Start信号已发出  if((TWSR&0xf8)!=0x08)      //或:if ((TWSR & 0xF8) != START),检测状态寄存器,屏蔽预分频位,如果状态字不是START转出错处理      return(1);             //返回值1,表明从机没有对Start信号作应答         

    //Slave即SLA+W,即是从机地址 ,可以是0x18或0x20,此处只用0x18 //所谓的应答是“从器件”在收到地址和“写”后,将SDA电压拉低,由“主器件”读取 //ATmge16如果读到这个“低”电压则返回0x18,否则返回0x20。  TWDR=Slave;                //更新地址寄存器,装Slave入到TWDR寄存器  TWCR=0x80|0x04;            //或:TWCR = (1<<TWINT) | (1<<TWEN);对TWINT写1清除,使能TWI;发出从机地址信息  while((TWCR&0x80)!=0x80) ; //或:while (!(TWCR & (1<<TWINT)));等待TWINT置位,表明Slave信号已发出  if((TWSR&0xf8)!=0x18)     //或:if ((TWSR & 0xF8) != MT_SLA_ACK),检测状态寄存器,     return(2);              //返回值2,表明从机没有对Slave信号作应答

    //Address是MT_SLA_ACK是否控发送器地址,可以是0x28或0x30, 此处只用0x28  TWDR=Address;  TWCR=0x80|0x04;            //或:TWCR = (1<<TWINT) | (1<<TWEN);对TWINT写1清除,使能TWI;发出寄存器地址信息  while((TWCR&0x80)!=0x80) ; //或:while (!(TWCR & (1<<TWINT)));等待TWINT置位,表明Address信号已发出  if((TWSR&0xf8)!=0x28)     //检测状态寄存器(MT_DATA_ACK)     return(3);              //返回值3,表明从机没有对Address信号作应答    TWDR=Data;//写数据到ZLG7290  TWCR=0x80|0x04;            //或:TWCR = (1<<TWINT) | (1<<TWEN);对TWINT写1清除,使能TWI;发出数据信息  while((TWCR&0x80)!=0x80) ; //或:while (!(TWCR & (1<<TWINT)));等待TWINT置位,表明Data信号已发出  if((TWSR&0xf8)!=0x28)     //if ((TWSR & 0xF8) != MT_DATA_ACK);检测状态寄存器     return(4);              //返回值3,表明从机没有对Data信号作应答    TWCR=0x80|0x04|0x10;       //或:TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);对TWINT写1清除,使能TWI,发出Stop信号  return(0);   }

     

    /****************************************************************** ********************************************************************* 向IIC地址为Slave的从机的Address地址开始发送N字节数据Data ****************************************************************** *******************************************************************/ uchar TWI_Send_Mux(uchar Slave,uchar Address,uchar *Array,uchar CNT) {uchar Count;  TWCR=0x80|0x20|0x04;       //对TWINT写1清除,使能TWI,发出Start信号  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Start信号已发出  if((TWSR&0xf8)!=0x08)      //检测状态寄存器      return(1);             //返回值1,表明从机没有对Start信号作应答             TWDR=Slave;                //更新地址寄存器  TWCR=0x80|0x04;            //对TWINT写1清除,使能TWI;发出从机地址信息  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Slave信号已发出  if((TWSR&0xf8)!=0x18)     //检测状态寄存器     return(2);              //返回值2,表明从机没有对Slave信号作应答    TWDR=Address;  TWCR=0x80|0x04;            //对TWINT写1清除,使能TWI;发出寄存器地址信息  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Address信号已发出  if((TWSR&0xf8)!=0x28)     //检测状态寄存器     return(3);              //返回值3,表明从机没有对Address信号作应答    for(Count=0;Count<CNT;Count++) //连续写N个字节 ,实现发送N字节数据Data     {TWDR=Array[Count];         //建立数组装载TWDR          TWCR=0x80|0x04;            //或(1<<TWINT)|(1<<TWEN);对TWINT写1清除,使能TWI;发出数据信息      while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Data信号已发出      if((TWSR&0xf8)!=0x28)      //检测状态寄存器         return(4);}             //返回值4,表明从机没有对Data信号作应答    TWCR=0x80|0x04|0x10;           //对TWINT写1清除,使能TWI,发出Stop信号  return(0); }

    /********************************************************************** *********************************************************************** 从IIC地址为Slave的从机的Address地址读取一字节数据Data,返回值为读取的数据 ************************************************************************ ***********************************************************************/ //以下为主机接收模式 /*在主机接收模式,主机可以从从机接收数据,为进入主机模式,必须发送START信号。 紧接着的地址包格式决定进入MT或MR模式。 如果发送 SLA+W 进入MT模式;如果发送SLA+R则进入MR模式。*/ uchar TWI_Receive(uchar Slave,uchar Address) {//发送Start  uchar Temp;  TWCR=0x80|0x20|0x04;       //或:TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);对TWINT写1清除;使能TWI;发出Start信号  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Start信号已发出  if((TWSR&0xf8)!=0x08)      //检测状态寄存器,{0x08表示:主机的TWSR状态码(在预分频位为"0"情况下)}      return(1);             //返回值1,表明从机没有对Start信号作应答           //发送Slave+W  TWDR=Slave;                //更新地址寄存器  TWCR=0x80|0x04;            //对TWINT写1清除,使能TWI;发出从机地址信息  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Slave信号已发出  if((TWSR&0xf8)!=0x18)     //检测状态寄存器,(0x18表示:SLA+W从机已发送,接收到ACK)     return(2);              //返回值2,表明从机没有对Slave信号作应答  //发送Address  TWDR=Address;  TWCR=0x80|0x04;            //对TWINT写1清除,使能TWI;发出寄存器地址信息  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Address信号已发出  if((TWSR&0xf8)!=0x28)     //检测状态寄存器,(0x28表示:主控机地址已发送,接收到ACK)     return(3);              //返回值3,表明从机没有对Address信号作应答

    //上面三段程序定义是主机方式后,以下就是接收信号的定义

     //发送Start,重新启动TWI  TWCR=0x80|0x20|0x04;       //对TWINT写1清除;使能TWI;发出Start信号  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Start信号已发出  if((TWSR&0xf8)!=0x10)      /*检测状态寄存器,在Repeat Start (状态0x10) 后,两线接口可以再次访问                             相同的从机,或不发送STOP信号来访问新的从机。REPEATED START使得主机                                                         可以在不丢失总线控制的条件下在从机、主机发送器及主机接收器模式间进行切换。*/      return(4);             //返回值4,表明从机没有对Repeat Start信号作应答           //发送Slave+R  TWDR=Slave+1;              //更新地址寄存器  TWCR=0x80|0x04;            //对TWINT写1清除,使能TWI;发出从机地址信息  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明Slave信号已发出  if((TWSR&0xf8)!=0x40)     //检测状态寄存器,(0x40表示:SLA+R(MR_SLA_ACK)已发送,接收到ACK)     return(5);              //返回值5,表明从机没有对Slave+R信号作应答    TWCR=0x80|0x04;            //对TWINT写1清除,使能TWI;接受数据  while((TWCR&0x80)!=0x80) ; //等待TWINT置位,表明数据已经接收接受  if((TWSR&0xf8)!=0x50)  ;   //检测状态寄存器,(0x50表示:接收到数据,ACK已返回)    // return(6);              //返回值3,表明从机没有对Address信号作应答    Temp=TWDR;                 //读接收数据    TWCR=0x80|0x04;            //发出NACK信号    TWCR=0x80|0x04|0x10;       //发出Stop信号,或:TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);  DelayMs(1*2);  TWCR=0x80;                 //清除TWINT和禁止TWI(不加上这句程序只能读一次)  return(Temp); }

     

     

    /********************************************************************************************/ /*************************以下是对ZLG7290的定义和使用****************************************/ /********************************************************************************************/ /**************************ZLG7290库函数程序**************************************************/

     

     

     

    /*ZLG7290的I2C接口传输速率可达32kbit/s,容易与处理器接口.并提供键盘中断信号,提高主处 理器时间效率.ZLG7290的从地址 (slave address)为70H(01110000B).*/

     

    /*ZLG7290B的I2C总线器件地址是70H(写操作)和71H(读操作).*/

     

    /*ZLG7290提供两种控制方式:寄存器映象控制和命令解释控制, 寄存器映象控制是指直接访问底层寄存器,实现基本控制功能,这些寄存器须字节操作  命令解释控制是指通过解释命令缓冲区(CmdBuf0CmdBuf1)中的指令,间接访问底层寄存器实 现扩展控制功能.如实现寄存器的位操作,对显示缓存循环,移位;对操作数译码等操作.*/

     

    //***************寄存器映象控制******************// /*********************************************************************** ** 函数名称:         ZLG7290_SendData ** 功能描述:         发送数据 ** 输 入:SubAdd :        输入数据 **       DATA         :        输入值 **          ** 输 出: 0 : Fail **        1 :  OK ** 全局变量:        无 ** 调用模块:         delayMS **-------------------------------------------------------------------------------------------------- ***********************************************************************/ //功能:向器件地址为zlg7290的ZLG7290芯片的SubAdd地址的寄存器写一字节Data uchar ZLG7290_SendData(uchar SubAdd,uchar Data) {         if(SubAdd>0x17)//0x17表示:DpRam0~7的最大地址,它的范围是(0x10~0x17),共八位数码管                 return 0;//超出于0x17的范围,即超出八位数码管数目就返回0         TWI_Send(zlg7290,SubAdd,Data);//TWI_Send()为发送一字节,zlg7290表示从机,SubAdd为地址,Data为数据         DelayMs(10*2);         return 1; }

    /************发送命令函数***********************/ /*********************************************************************** ** 函数名称:         ZLG7290_SendCmd ** 功能描述:         发送命令(对子地址7、8) ** 输 入:DATA1  :        命令1 **       DATA2         :        命令2 **          ** 输 出: 0 : Fail **        1 :  OK ** 全局变量:        无 ** 调用模块:         TWI_Send_Mux、delayMS **-------------------------------------------------------------------------------------------------- ***********************************************************************/

    //功能:向命令缓冲区0x07、0x08发送命令,(0x07~0x08是CmdBuf0~2命令接口:包括译码,移位) // 寄存器CmdBuf0(地址:07H)和CmdBuf1(地址:08H)共同组成命令缓冲区。 //通过向命令缓冲区写入相关的控制命令可以实现段寻址、下载显示数据、控制闪烁等功能 uchar ZLG7290_SendCmd(uchar Data1,uchar Data2) {uchar Data[2];         Data[0]=Data1;         Data[1]=Data2;         TWI_Send_Mux(zlg7290,0x07,Data,2);//TWI_Send_Mux()发送N个字节(这里N为2),zlg7290为从机,0x07是地址         DelayMs(10*2);         return 1; }  

    //***********向显示缓冲区送显示数据***************// /*********************************************************************** ** 函数名称:         ZLG7290_SendBuf ** 功能描述:         向显示缓冲区发送数据 ** 输 入: * disp_buf          :        要发送数据的起始地址 **         num                 :        发送个数 **          ** 输 出: 无 ** 全局变量:        无 ** 调用模块:         ZLG7290_SendCmd **-------------------------------------------------------------------------------------------------- ***********************************************************************/

    //功能:送显示数据。需要给出显示缓冲区首址和显示的数据个数(<8个) /*显示缓存寄存器(DpRam0~DpRam7):地址10H~17H,复位值00H~00H.缓存中一位置 1表示该像素亮,DpRam7~DpRam0的显示内容对应Dig7~Dig0引脚 */ void ZLG7290_SendBuf(uchar *disp_buf,uchar num) {uchar i;         for(i=0;i<num;i++)         {                         ZLG7290_SendCmd(0x60+i,*disp_buf);//在第i位数码管译码并显示DpBuf[i]                 disp_buf++;                 DelayMs(10*2);         } }

    //***********取得按键编号****************// /*********************************************************************** ** 函数名称:         ZLG7290_GetKey ** 功能描述:         读取键值 ** 输 入: 无 **          ** 输 出: >0  键值 **        =0  无键按下 ** 全局变量:        无 ** 调用模块:         TWI_Receive、delayMS ** **------------------------------------------------------------------------------------------------- ***********************************************************************/ uchar ZLG7290_Ledstatus(uchar status){switch(status) {case IDEL:            ZLG7290_SendCmd(1,0x00);            ZLG7290_SendCmd(1,0x01);          ZLG7290_SendCmd(1,0x02);          break;   case RUN:          ZLG7290_SendCmd(1,0x80);            ZLG7290_SendCmd(1,0x01);          ZLG7290_SendCmd(1,0x02);          break;   case WARING:          ZLG7290_SendCmd(1,0x00);            ZLG7290_SendCmd(1,0x81);          ZLG7290_SendCmd(1,0x02);          break;                  case FAULT:          ZLG7290_SendCmd(1,0x00);            ZLG7290_SendCmd(1,0x01);          ZLG7290_SendCmd(1,0x82);          break;     } return 0;}uchar ZLG7290_GetKey() {uchar rece;         rece=0;         rece=TWI_Receive(zlg7290,1);//键值寄存器Key地址是01H,所以此处Address=1;zlg7290为从机         DelayMs(10*2);         return rece; }

    uchar ZLG7290_GetFuncKeyNum(){ uchar rece; rece=0; rece=TWI_Receive(zlg7290,3); DelayMs(10*2); return ~rece;}

    uchar GetKey(){    uchar key=0xff;   if((PIND&0x04)==0)  

      {   key=ZLG7290_GetKey();   //取得按键数值   if(key==0)    key=0xf0|ZLG7290_GetFuncKeyNum();   }  if(key!=0xff)       return key;    return 0;}


    最新回复(0)