jessie9940509 发表于 2007-7-10 22:24:01

马老师 模拟I2C总线 读写2402的问题

马老师:我用的16的AVR写的口线模拟I2C读写2402的程序,为什么写进去的时候判断回应位可以的,读2402时判断回应位就有问题了。因为我原来用162写2402的,PD4,PD5做SDA,SCL但是有问题。所以我又用16试的,选择PA0做SCL,PA1做SDA 别的口线复用功能太多,我也不知道有没有屏蔽掉。

以下是源程序

//ICC-AVR application builder : 2007-5-29 9:41:16

// Target : M16

// Crystal: 11.059Mhz



#include <iom16v.h>

#include <macros.h>

#include <eeprom.h>

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

//通讯部分的参数定义

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

char data_send;            //要发送的数据

char data_rev;          //接收的所有数据的数组

char send_step;            //发送数据步数

char rev_lenth;            //接收到的数组长度

char rev_counter;            //接收数据总计数器

char data_counter;         //接收的数组计数器

char check;                  //校验码

char send_counter;

char eep_test;

char eep_test2;

char i2cr;

char i2cs;

char mydata;

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

//处理接受数据的参数定义

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

char nm_24c02;          //从24C02读出的全部内码数组

char i2cr;                   //存放从24C02读出的一个字节数据

char i2cs;

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

//时间参数定义

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

char count_20ms;             //20MS计数器

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

struct data

{

unsigned bit0:1;         //发送开始标志位

unsigned bit1:1;         //接收完成标志位

unsigned bit2:1;         //发送成功标志位

unsigned bit3:1;         //接收开始标志位

} sign,time;

unsigned int count_1ms;

void port_init(void)

{

PORTA = 0xFF;

DDRA= 0xFF;

PORTB = 0xFF;

DDRB= 0x0F;

PORTC = 0xff;               //m103 output only

DDRC= 0x03;

PORTD = 0x00;

DDRD= 0x03;

}



//TIMER0 initialisation - prescale:64

// WGM: Normal

// desired value: 1mSec

// actual value:0.995mSec (0.5%)

void timer0_init(void)

{

TCCR0 = 0x00;            //stop

TCNT0 = 0x54;            //set count

OCR0= 0xAC;            //set compare

TCCR0 = 0x03;            //start timer

}



#pragma interrupt_handler timer0_ovf_isr:10

void timer0_ovf_isr(void)

{

TCCR0 = 0x00; //stop

TCNT0 = 0x54; //reload counter value

count_20ms++;

if(count_20ms>=20)

    {

      time.bit0=1;       //20ms

      count_20ms=0;

    }

TCCR0 = 0x03; //start timer

}



//UART0 initialisation

// desired baud rate: 9600

// actual: baud rate:9600 (0.0%)

// char size: 8 bit

// parity: Disabled

void uart0_init(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x00;

UCSRC = 0x86;

UBRRL = 0x47; //set baud rate lo

UBRRH = 0x00; //set baud rate hi

UCSRB = 0xD8;

}



#pragma interrupt_handler uart0_rx_isr:12

void uart0_rx_isr(void)

{



char recieve_data;            //每次接收数据的缓冲器

//uart has received a character in UDR

recieve_data=UDR;



switch(rev_counter)

{

case 0: if (recieve_data==0xfe)

         {

          rev_counter++;

         //PORTA|=0xfC;

         check+=0XFE;

         }

         else

         {

         check=0;

         rev_counter=0;

         

         }

         break;

case 1: if(recieve_data==0xfe)   

         {

         rev_counter++;

         //PORTA=0XFD;

         check+=0XFE;

         }   

         else

         {

         check=0;

         rev_counter=0;

         }

         break;

case 2:if(recieve_data==0x68)   

         {

         rev_counter++;

         //PORTA=0XFB;

         check+=0X68;

         }   

         else

         {

         check=0;

         rev_counter=0;

         }

         break;

case 3: rev_lenth=recieve_data;if(rev_lenth==0x1A){rev_counter++;check+=0X1A;}break;      

default:{

         if(rev_counter>=4)

          {

         data_counter++;

            if(data_counter<=rev_lenth)

               {

               data_rev=recieve_data;

                rev_counter++;

               check+=data_rev;

               }

            else

               {

                  if (data_counter==rev_lenth+1)

                      {

                  //PORTA=0XEF;                        //第5个灯亮

                     if(check==recieve_data)

                        {

                     //PORTA=0XDF;                  //第6个灯亮

                         rev_counter++;

                         check=0;

                        }

                     else

                     {

                     rev_counter=0;

                     check=0;

                     recieve_data=0;

                      }

                      }

               if (data_counter==rev_lenth+2)

                   {

                      //PORTA=0XBF;                     //第7个灯亮

                      if (recieve_data==0xAA)

                      {

                      //PORTA=0X7F;                  //全部正确,最后一个灯亮

                      sign.bit1=1;                   //置成功接收标志位                              

                     }   

                        

                      rev_counter=0;

                      check=0;

                      recieve_data=0;

                      data_counter=0;

                   }

               }

         }

         }

            

}

   

}



#pragma interrupt_handler uart0_tx_isr:14

void uart0_tx_isr(void)

{   



switch (send_step)

{

case 1:send_step=2;UDR=0x4B;PORTB |=0x02;PORTB &=~0x04;break;

case 2:send_step=3;break;//send_step=2;UDR=nm_24c02;send_counter++;if(send_counter>=rev_lenth){send_step=3;}break;

case 3:send_step=0;sign.bit1=0; sign.bit0=0;break;

default:break;

}

   //character has been transmitted

}



//call this routine to initialise all peripherals

void init_devices(void)

{

//stop errant interrupts until set up

CLI(); //disable all interrupts

port_init();

//timer0_init();

//uart0_init();



MCUCR = 0x00;

GICR= 0x00;

TIMSK = 0x00; //timer interrupt sources

SEI(); //re-enable interrupts

//all peripherals are now initialised

}

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

//                                                       24C02部分

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

void delay_1ms()

{

unsigned int delay_1;

for(delay_1=0;delay_1<1571;delay_1++)

;

}

void delay(unsigned int n)                              

{

unsigned int delay_2=0;

for(delay_2=0;delay_2<n;delay_2++)

   {

   delay_1ms();

   }

}

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

void delay_1us()

{

asm("nop");

asm("nop");

asm("nop");

}

void delayus(unsigned int m)

{

unsigned int delay_3=0;

for(delay_3=0;delay_3<m;delay_3++)

delay_1us();

}

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

//24c02测试区

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

void i2c_start()

{

   //C2402_SDA=1;   /*发送起始条件的数据信号*/

   PORTA|=0X02;

   delayus(10); /*起始条件建立时间大于4.7us,延时*/

   //C2402_SCL=1;

   PORTA|=0X01;

   delayus(10);   /*起始条件建立时间大于4.7us,延时*/

   //C2402_SDA=0;   /*发送起始信号*/

   PORTA&=~0X02;

   delayus(10);    /* 起始条件锁定时间大于4μs*/

   //C2402_SCL=0;   /*钳住I2C总线,准备发送或接收数据 */

   PORTA&=~0X01;

   delayus(10);    /*起始条件建立时间大于4.7us,延时*/

}

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

void i2c_stop()

{

//C2402_SDA=0;/*发送结束条件的数据信号*/

PORTA&=~0X02;

delayus(10);   /*发送结束条件的时钟信号*/

//C2402_SCL=0;/*结束条件建立时间大于4μs*/

PORTA&=~0X01;

delayus(10);

//C2402_SCL=1;/*发送I2C总线结束信号*/

PORTA|=0X01;

delayus(10);

//C2402_SDA=1;

PORTA|=0X02;

delayus(10);

}

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

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

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

void i2c_send()

{

   unsigned char count_i2cs;

   for(count_i2cs=0;count_i2cs<8;count_i2cs++)

   {

      if(((i2cs<<count_i2cs)&0x80)==0)

      {

         //C2402_SDA=0;

             PORTA&=~0X02;

      }

      else

      {

         //C2402_SDA=1;

            PORTA|=0X02;

      }

      delayus(10);

      //C2402_SCL=1;

      PORTA|=0X01;

      delayus(10);

      //C2402_SCL=0;

       PORTA&=~0X01;

       delayus(10);

    }

   //C2402_SDA=1;

       PORTA|=0X02;

      delayus(10);

   //C2402_SCL=1;

       PORTA|=0X01;

      delayus(10);

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

      //PIND=0XFF;

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

      //while(C2402_SDA==1)

      //PORTA&=~0X08;

      DDRA&=~0x02;

      //delayus(20);

      PORTA&=~0X02;

      //PORTA|=0X02;

      //delayus(20);

      while((PINA&0X02)==0X02)

       {

      ;

       }

       delayus(10);                  //灯亮,通过

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

      DDRA|=0X02;

      delayus(10);

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

      //C2402_SCL=0;

      PORTA&=~0X01;

      delayus(10);

}

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

void i2c_send2()

{

   unsigned char count_i2cs;

   for(count_i2cs=0;count_i2cs<8;count_i2cs++)

   {

      if(((i2cs<<count_i2cs)&0x80)==0)

      {

         //C2402_SDA=0;

             PORTA&=~0X02;

      }

      else

      {

         //C2402_SDA=1;

             PORTA|=0X02;

      }

      delayus(10);

      //C2402_SCL=1;

      PORTA|=0X01;

      delayus(10);

      //C2402_SCL=0;

       PORTA&=~0X01;

      delayus(10);

    }

   //C2402_SDA=1;

       PORTA|=0X02;

      delayus(10);

   //C2402_SCL=1;

       PORTA|=0X01;

      delayus(10);

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

      //PIND=0XFF;

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

      //while(C2402_SDA==1)

      //PORTA&=~0X08;

      DDRA&=~0x02;

      //delayus(20);

      PORTA&=~0X02;

      while((PINA&0X02)==0X02)

       {

      ;

       }

      PORTA &=~0XFC;                      //灯不亮了没有通过

       delayus(10);

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

      DDRA|=0X02;

      delayus(10);

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

      //C2402_SCL=0;

      PORTA&=~0X01;

      delayus(10);

}

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

void i2c_rece()

{

   unsigned char count_i2cr;

   //C2402_SCL=0;

    PORTA&=~0X01;

    i2cr=0;

    delayus(10);

   //C2402_SDA=1;

    PORTA|=0X02;

    DDRA&=~0x02;

   delayus(10);

   PORTA|=0X02;

   for(count_i2cr=0;count_i2cr<8;count_i2cr++)

   {

       //C2402_SCL=1;

       PORTA|=0X01;

      delayus(10);

      i2cr=i2cr<<1;

      //if(C2402_SDA==1)

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

      

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

      if((PINA&0X02)==0X02)

          {

         i2cr=i2cr+1;

         }

         delayus(10);

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

       //DDRD|=0X02;

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

       //C2402_SCL=0;

      

       PORTA&=~0X01;

      delayus(10);

   }

   DDRA|=0x02;

   delayus(10);

}

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

//

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

void i2c_read(void)

{

   unsigned char count_read=0;

      i2c_start();

       i2cs=0xa0;

      i2c_send2();

      delayus(10);

      i2cs=0x30;

      i2c_send2();

      i2c_start();

      i2cs=0xa1;

      i2c_send2();

      delayus(10);

      i2c_rece();

      mydata=i2cr;   //0x30里的内容读到NM_LENGRH

      i2c_stop();

      delayus(10);



}

void i2c_write(void)

{

unsignedcharcount_wirte,count_write1;

   

    i2c_start();

   i2cs=0xa0;

    i2c_send();

   delayus(10);

    i2cs=0x30;

    i2c_send();

   delayus(10);

   i2cs=rev_lenth;

   i2c_send();

   delayus(10);

   i2c_stop();

    delayus(10);

}

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

void main(void)

{

init_devices();

//PORTA=0X00;

delay_1us(50);

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

data_rev=0x00;

data_rev=0x01;

data_rev=0x02;

data_rev=0x03;

data_rev=0x04;

data_rev=0x05;

data_rev=0x06;

data_rev=0x07;

rev_lenth=0x08;

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

//insert your functional code here...

i2c_write();

PORTB |=0x04;

PORTB &=~0x02;

i2c_read();

   

   if(mydata==0x08)

   {

      PORTA&=~0XFC;

   }



}

jessie9940509 发表于 2007-7-10 22:27:57

PORTA&=~0XFC是点亮几个灯.我用来试我的程序有没有死机用的.同时也用来检验我写进2402的数对不对

jessie9940509 发表于 2007-7-12 09:20:07

马老师帮帮忙吧。我是个菜鸟,别打击我的积极性。我快崩溃了。

jessie9940509 发表于 2007-7-13 21:27:26

马老师,请您帮忙指点一下把!!!

jessie9940509 发表于 2007-7-16 14:20:42

马老师救命啊!!!指点一下即可!!

jessie9940509 发表于 2007-7-18 21:03:17

马老师救命啊!!!指点一下即可!!

machao 发表于 2007-8-11 17:13:09

这不是几句话能讲清的,你在网上找点例程参考吧,还是有2-3个的。



我的教材大约10月出版,那里面有对24C256操作的例子,介绍了4种实现方法,有使用I/O模拟的,有使用CVAVR提供的函数的(也是I/O模拟的),有采用硬件TWI实现的等。不过可能时间上等不及了。
页: [1]
查看完整版本: 马老师 模拟I2C总线 读写2402的问题