<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        ATMEGA16—AT24C1024存儲

        作者:蕭文   來源:本站原創   點擊數:  更新時間:2014年04月01日   【字體:

        總算是把這些問題統統解決了~~

        現在貼出來~~

        一個哥幫了忙~~

        ~~

        不過以前的錯誤還是有好幾點的~~

        AT24C1024存儲:

        老規矩~~

        顯示上圖~~





        然后是程序:(里面有重點要關注的~~)

        IAR7_1.c

        //------------------------------------------------------------------------------
        //IAR7_1.c
        //向AT24C1024指定地址寫入一個數據,然后從中讀出來~~
        #include"ioavr.h"
        #include"lcdinit.h"
        #include"at24c1024.h"
        #include"delayics.h"
        //------------------------------------------------------------------------------
        uchar __flash title0[]="Write:";
        uchar __flash title1[]="Read:";
        uchar __flash test[]="_Justin";
        //uchar __flash display[7]={0,0,0,0,0,0,0};
        //------------------------------------------------------------------------------
        //端口初始化函數
        void port_init()
        {
          DDRA=0XFF;
          PORTA=0XFF;
          DDRB=0XFF;
          PORTB=0XFF;
         
          DDRC=0XFF;
          PORTC=0X00;
          DDRD=0X00;
          PORTD=0XFF;
        }
        //------------------------------------------------------------------------------
        //main
        void main()
        {
          uchar display[7];
          port_init();
          twi_init();                          
          lcd_init();
          lcd_display_string(0,0,title0,6);
          lcd_display_string(1,0,title1,5);

         
          mcu_send_string(0xa0,0x00,0x00,test,7);
          delay_s(1);
          mcu_receive_string(0xa0,0x00,0x00,display,7);
         
          lcd_display_string(0,9,test,7);
          lcd_display_char(1,9,display[0]);
          lcd_display_char(1,10,display[1]);
          lcd_display_char(1,11,display[2]);
          lcd_display_char(1,12,display[3]);
          lcd_display_char(1,13,display[4]);
          lcd_display_char(1,14,display[5]);
          lcd_display_char(1,15,display[6]);
          while(1);
        }

        LCDInit.c

        //------------------------------------------------------------------------------
        //LCD1602的初始化程序—可調用函數—Atmega 16
        #include"ioavr.h"
        #include"intrinsics.h"
        #include"delayics.h"
        #include"bitics.h"
        #include"lcdinit.h"
        //------------------------------------------------------------------------------
        //RS、RW、EN引腳輸出高低電平的宏定義
        #define lcd_rs_1  SET_BIT(PORTB,0)          //數據命令選擇端
        #define lcd_rs_0  CLR_BIT(PORTB,0)
        #define lcd_rw_1  SET_BIT(PORTB,1)          //讀寫命令選擇端         
        #define lcd_rw_0  CLR_BIT(PORTB,1)
        #define lcd_en_1  SET_BIT(PORTB,2)          //使能信號
        #define lcd_en_0  CLR_BIT(PORTB,2)
        //------------------------------------------------------------------------------
        #define data_port PORTA
        #define busy  0x80
        //------------------------------------------------------------------------------
        //檢測LCD忙函數
        void lcd_check_busy()
        {
          uchar temp;
          data_port=0xff;
          lcd_rs_0;
          lcd_rw_1;                                 //讀指令
          delay_ms(1);
          lcd_en_1;
          delay_ms(1);
          DDRA=0X00;                                //設置端口A為輸入
          temp=PINA;                                //取端口A的值
          while(temp&busy)                          //當D7為0時可以結束whlie循環,繼續執行下面的操作
            temp=PINA;
          lcd_en_0;
          DDRA=0xff;
        }
        //------------------------------------------------------------------------------
        //LCD寫數據函數
        void lcd_write_data(uchar dat)
        {
          lcd_check_busy();
          lcd_rs_1;
          lcd_rw_0;
          data_port=dat;
          delay_ms(1);
          lcd_en_1;                                //LCD的使能端高電平有效,當E端由高電平跳變成低電平時,液晶模塊執行命令
          delay_ms(1);                             //送個延時
          lcd_en_0;
        }
        //------------------------------------------------------------------------------
        //LCD寫指令函數
        //其中flag的作用是為0不進行忙檢測,為非0則進行忙檢測
        void  lcd_write_command(uchar com,uchar flag)
        {
          if(flag)
            lcd_check_busy();
          lcd_rs_0;
          lcd_rw_0;
          data_port=com;
          delay_ms(1);
          lcd_en_1;                               //E端由高電平跳變成低電平時,液晶模塊執行命令
          delay_ms(1);                            //送個延時
          lcd_en_0;
        }
        //------------------------------------------------------------------------------
        //LCD初始化函數
        //如果Proteus仿真不顯示,那就更改初始化就哦了~~
        void lcd_init()
        {
          lcd_write_command(0x38,0);   //8位數據傳送,兩行顯示,5*7字形,不檢測忙信號
          delay_ms(3);
          lcd_write_command(0x38,0);
          delay_ms(3);
          lcd_write_command(0x38,0);
          delay_ms(3);
          lcd_write_command(0x38,1);  //8位數據傳送,兩行顯示,5*7字形,檢測忙信號
          lcd_write_command(0x08,1);  //關閉顯示,檢測忙信號
          lcd_write_command(0x01,1);  //清屏,檢測忙信號 
          delay_ms(1);                //一定要有一個延時~~這就是Proteus仿真的差距~~
          lcd_write_command(0x06,1);  //顯示光標右移設置,檢測忙信號
          lcd_write_command(0x0c,1);  //顯示屏打開,光標不顯示,不閃爍,檢測忙信號
        }
        //------------------------------------------------------------------------------
        //LCD顯示一個字節函數
        void  lcd_display_char(uchar row,uchar add,uchar dat)
        {
          switch(row)
          {
          case 0:
            lcd_write_command(0x80+add,1);
            lcd_write_data(dat);
            break;
            //------------------------------------------------------------------------------
           case 1:
            lcd_write_command(0x80+0x40+add,1);
            lcd_write_data(dat);
            break;
          default:
            break;
          }
        }
        //------------------------------------------------------------------------------
        //LCD顯示多個字節函數
        void  lcd_display_string(uchar row,uchar add,uchar __flash *s,uchar num)
        {
          uchar i;
          switch(row)
          {
          case 0:
            lcd_write_command(0x80+add,1);
            for(i=0;i<num;i++)
            {
             lcd_write_data(s[i]);
            }
            break;
            //------------------------------------------------------------------------------
           case 1:
            lcd_write_command(0x80+0x40+add,1);
            for(i=0;i<num;i++)
            {
             lcd_write_data(s[i]);
            }
            break;
          default:
            break;
          }
        }
        AT24C1024.c

        //------------------------------------------------------------------------------
        //AT24C1024文件的函數,便于以后調用
        #include"ioavr.h"
        #include"intrinsics.h"
        #include"bitics.h"
        #include"delayics.h"
        #include"lcdinit.h"
        //------------------------------------------------------------------------------
        typedef unsigned char uchar;
        typedef unsigned int  uint;
        #define TWINT 7
        #define TWEA  6
        #define TWSTA 5
        #define TWSTO 4
        #define TWEN  2
        //------------------------------------------------------------------------------
        //TWI狀態定義:MT主方式傳輸;MR從方式傳輸
        //這里就是與TWI狀態寄存器進行比較的~~如果一致則繼續,如果不一致則終止
        //注意:狀態寄存器一定要屏蔽掉預分頻位
        #define START 0x08                 //我寫錯了~~
        #define RE_START 0x10
        #define MT_SLA_ACK 0x18
        #define MT_SLA_NOACK 0x20
        #define MT_DATA_ACK 0x28
        #define MT_DATA_NOACK 0x30
        #define MR_SLA_ACK 0x40
        #define MR_SLA_NOACK 0x48
        #define MR_DATA_ACK 0x50
        #define MR_DATA_NOACK 0x58
        //------------------------------------------------------------------------------
        //常用TWI模式操作(主模式寫和主模式讀)
        #define twi_start()         (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))      //啟動信號的宏定義
        #define twi_stop()          (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))      //停止信號的宏定義
        #define twi_wait()          {while(!(TWCR&(1<<TWINT)));}                //等待的宏定義
        #define twi_test_ack()      (TWSR&0xf8)                                 //屏蔽掉預分頻位,測試應答信號的宏定義
        #define twi_send_ack()      (TWCR|=(1<<TWEA))                           //發送應答信號的宏定義
        #define twi_send_noack()    (TWCR&=~(1<<TWEA))                          //發送非應答信號的宏定義
        #define twi()               (TWCR=(1<<TWINT)|(1<<TWEN))                 //啟動TWI器件的宏定義
        #define twi_write_char(x)   {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}       //發送8位數據的宏定義
        //------------------------------------------------------------------------------
        //TWI初始化函數
        //這個函數我試過~~如果不進行具體的設置可以要也可以不要~~不過也是初始化的一個過程~~所以寫出來~~
        void twi_init()
        {
          TWBR=0X00;                                        //波特率
          TWSR=0X00;                                        //不分頻
          TWAR=0X00;                                        //被控地址寄存器
          TWCR=(1<<TWEA)|(1<<TWEN);                         //允許ACK,使能IIC,PC0、PC1轉換成SCL、SDA
        }
        //------------------------------------------------------------------------------
        //向器件指定地址按頁寫函數(這里你可以選擇你要寫入的個數num~~)
        //寫入成功,返回1;不成功,返回0,使用后必須結束總線
        uchar mcu_send_string(uchar add,uchar rom_add_h,uchar rom_add_l,uchar __flash *s,uchar num)
        {
          uchar i;
          twi_start();                                      //發送起始信號
          twi_wait();
          if(twi_test_ack()!=START)
            return(0);
         
          twi_write_char(add);                              //發送從器件AT24C1024地址
          twi_wait();
          if(twi_test_ack()!=MT_SLA_ACK)
            return(0);
         
          twi_write_char(rom_add_h);                        //發送器件的ROM地址高字節
          twi_wait();
          if(twi_test_ack()!=MT_DATA_ACK)
            return(0);
         
          twi_write_char(rom_add_l);                        //發送器件的ROM地址低字節
          twi_wait();
          if(twi_test_ack()!=MT_DATA_ACK)
            return(0);
         
          for(i=0;i<num;i++)                               //頁寫,寫入num個數據
          {
            twi_write_char(*s);
            twi_wait();
            if(twi_test_ack()!=MT_DATA_ACK)
              return(0);
            s++;
          }
         
          twi_stop();                                      //發送停止
          delay_ms(2);
          return(1);
        }
        //------------------------------------------------------------------------------
        //從器件指定地址讀多個字節(這里你可以選擇你要讀出的個數num~~)
        //寫入成功返回1,不成功返回0
        uchar mcu_receive_string(uchar add,uchar rom_add_h,uchar rom_add_l,uchar *s,uchar num)
        {
          uchar i;
          twi_start();                                      //發送起始信號
          twi_wait();
          if(twi_test_ack()!=START)
            return(0);
         
          twi_write_char(add);                              //發送從器件AT24C1024地址
          twi_wait();
          if(twi_test_ack()!=MT_SLA_ACK)
            return(0);
         
          twi_write_char(rom_add_h);                        //發送器件的ROM地址高字節
          twi_wait();
          if(twi_test_ack()!=MT_DATA_ACK)
            return(0);
         
          twi_write_char(rom_add_l);                        //發送器件的ROM地址低字節
          twi_wait();
          if(twi_test_ack()!=MT_DATA_ACK)
            return(0);
         
          twi_start();                                      //重新啟動
          twi_wait();
          if(twi_test_ack()!=RE_START)                      //注意:這里必須是RE_START
            return(0);
         
          twi_write_char(add+1);                            //發送從器件AT24C1024地址,這里為讀,要加1
          twi_wait();
          if(twi_test_ack()!=MR_SLA_ACK)                    //注意:這里是MR_SLA_ACK
            return(0);
         
          for(i=0;i<num-1;i++)                              //接收num-1個數據,由于最后一個接收的數據不需要應答,所以要單獨寫   
          {
            twi();
            twi_send_ack();                                 //發送應答位,這里一定要先使能應答位,然后等待~~,出現相應的條件就會發送ACK~~
            twi_wait();
            if(twi_test_ack()!=MR_DATA_ACK)                 //這里是MR_DATA_ACK~~你懂得~~
              return(0);
           
            *s=TWDR;
            s++;
          }
         
          twi();                                          //接收第num個數據
          twi_send_noack();                               //發送非應答位,這里也要先置位~~出現相關條件時發送NOACK
          twi_wait();
          if(twi_test_ack()!=MR_DATA_NOACK)
            return(0);
         
          *s=TWDR;
         
          twi_stop();                                      //TWI停止
          delay_ms(2);
          return(1);
        }

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮