專(zhuān)注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

AVR單片機(jī)ATMEGA16 1602液晶驅(qū)動(dòng)程序及心得

作者:huqin   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年02月27日   【字體:

     首先,祝福各位同仁,光棍節(jié)快樂(lè)!  
     今天,給我最好的節(jié)日禮物就是,我自己研發(fā)的AVR微控制器芯片開(kāi)發(fā)板,1602液晶屏實(shí)驗(yàn)成功!我很欣慰.寫(xiě)了一整天的程序,反復(fù)實(shí)驗(yàn),最終在凌晨0點(diǎn).終于成功了.
    在此過(guò)程中,最大的問(wèn)題莫過(guò)于那個(gè)所謂配套的1602液晶屏數(shù)據(jù)手冊(cè)!這個(gè)手冊(cè)簡(jiǎn)直是誤人子弟,里面資料寫(xiě)的很含糊.并且有錯(cuò)誤,而導(dǎo)致我反復(fù)試驗(yàn)失敗,最終,我使用了通用的1602液晶屏數(shù)據(jù)手冊(cè),才得以成功.
      我自制的AVR開(kāi)發(fā)板尺寸和我買(mǎi)的51開(kāi)發(fā)板差不多大小,ATmega16最小系統(tǒng),8位數(shù)碼管,藍(lán)光流水燈,isp編程接口.過(guò)載保護(hù)保險(xiǎn)絲,兩個(gè)74hc573鎖存器.1602液晶屏都已焊接完成,萬(wàn)用板是12X18cm的單孔玻纖板(質(zhì)量不太好,便宜沒(méi)好貨).現(xiàn)在我才發(fā)現(xiàn)不夠用,模塊數(shù)量相同的兩塊實(shí)驗(yàn)板,手工焊接的一定要比機(jī)器印刷的大2~3倍才行.....
     沒(méi)辦法,我只能用5X7cm的萬(wàn)用板做小模塊,ADC模塊,DS1302時(shí)鐘模塊,激光二極管模塊等等,然后用杜邦線把它們和AVR核心板鏈接起來(lái),目前計(jì)劃是這樣的,往往計(jì)劃很豐滿,實(shí)際很骨感,傷腦筋啊,,,
    此次,首次接觸了12864大液晶,能顯示中文,和超聲波測(cè)距傳感器,這得好好研究一下,我一直想要了解一下2.4g無(wú)線傳輸模塊,和陀螺儀傳感器,還有GPS模塊,不過(guò)那些還早,把AVRATMEGA16學(xué)的差不多了,再了解,也不遲.
/*
          Program name:  AVR  ATMEGA16 1602驅(qū)動(dòng)程序

 
 初次實(shí)驗(yàn)通過(guò)時(shí)間:  2013-11-11 00:04:01  ^_^  ;
 
 注意:在bysy()函數(shù)中嚴(yán)重出錯(cuò)!下次注意!
 
 while((PINA&0x80)==0x80); 此語(yǔ)句檢測(cè)到PA7為零時(shí)終止循環(huán);表明空
 閑狀態(tài)
 
          心得:
       AVR單片機(jī)的IO口位操作比較復(fù)雜,
   由三個(gè)寄存器控制IO口的輸出與輸入;   
   DDRn(輸出/輸入控制) 寄存器;
PORTn(輸出時(shí)控制數(shù)據(jù),輸入時(shí)控制內(nèi)部上拉電阻)寄存器;
PINn(用于讀取IO口數(shù)據(jù))寄存器;
               最終校驗(yàn)通過(guò)時(shí)間:  2013年11月12日15:12:28
         
*/
#include <iom16v.h>
#include <macros.h>

#define uint8  unsigned char
#define uint16 unsigned int

//========IO口位操作========================================

void rs(uint8 h)   //數(shù)據(jù)/指令選擇操作;
{
  if(h)
    PORTB|=1<<3;  //置一;
  else
    PORTB&=~(1<<3); //清零;
}

void rw(uint8 h)   //讀/寫(xiě)選擇操作;
{
   if(h==0)
    {
 PORTB&=~(1<<4);  //清零;
}
   else
    {
 DDRA=0X00;
 PORTA=0XFF;
 PORTB|=1<<4;  //置一;
}

}

void e(uint8 h)   //傳輸使能位;
{
  if(h)
    {
 PORTB|=1<<5;   //置一;
}
  else
    PORTB&=~(1<<5);//清零;

}


//========================================================

void  ddra(uint8 h)   //PA口輸入輸出函數(shù);
{
    if(h)
{
 DDRA=0XFF;      //輸出模式;
 PORTA=0xff;
}
else
 
{DDRA=0X00; PORTA=0XFF; } //輸入模式并且有上拉;

}

void busy()    //繁忙檢測(cè);
{
   ddra(0);    //設(shè)置PA口為輸入,有上拉;
   do
   {
     e(0);     //傳輸使能為0;
rs(0);    //指令;
rw(1);    //讀;
e(1);     //e為高電平;
  
   }while((PINA&0x80)==0x80);//如果讀到數(shù)據(jù)是01111111,表示空閑狀態(tài),跳出循環(huán);
    e(0);
ddra(1);   //PA口輸出狀態(tài);
 
}

void delay()  //小延時(shí);
{
  uint8 j=0;
  j=1;

}

void w_cmd(uint8 cmd)
{
  busy();     //繁忙檢測(cè)通過(guò)時(shí),PA口為輸出狀態(tài),默認(rèn)輸出0xff;
  PORTA=cmd;  //向PA口裝載數(shù)據(jù);
  rs(0);      //指令;
  rw(0);      //寫(xiě)入;
  e(1);       //傳輸使能脈沖高;
  delay();    //延時(shí);
  e(0);       //傳輸使能脈沖低;

}

void w_dat(uint8 dat)
{
  busy();     //繁忙檢測(cè)通過(guò)時(shí),PA口為輸出狀態(tài),默認(rèn)輸出0xff;
  PORTA=dat;  //向PA口裝載數(shù)據(jù);
  rs(1);      //數(shù)據(jù);
  rw(0);      //寫(xiě)入;
  e(1);       //傳輸使能脈沖高;
  delay();    //延時(shí);
  e(0);       //傳輸使能脈沖低;

}

void init_1602()
{
  
   w_cmd(0x3c);  //寫(xiě)入顯示設(shè)置:8位數(shù)據(jù),兩行,5x10顯示;
   w_cmd(0x0c);  //整屏顯示,光標(biāo)不閃,字符不閃;
   w_cmd(0x06);  //寫(xiě)入一個(gè)數(shù)據(jù)時(shí)地址自動(dòng)加一.整屏不移動(dòng);
   w_cmd(0x01);  //寫(xiě)入'清屏'指令;
  
 
}

 

void display(uint8 addr ,uint8 dat )//可在任意位置顯示字符,
{                                   //addr地址,dat數(shù)據(jù);
  w_cmd(addr);
  w_dat(dat);
}

 

void main(void)        //====主函數(shù)=================

    uint8 i=0, j=0x80,ak[]="I'am iron man!"; //要顯示的字符串"我是鋼鐵俠!"
    uint8 sj[]="2013-11-11 ^_^";  //今天的日期;
    uint16 s=0;                  //16位的變量;
    DDRB=0XFF;           //PB口輸出狀態(tài);
PORTB=0X03;  //PB0=1;PB1=1;  
DDRA=0XFF;    //PA口輸出狀態(tài);    
PORTA=0X00;   //8個(gè)數(shù)碼管共陰極為'0'.八位陽(yáng)極為'0';
PORTB=0X00;   //鎖存數(shù)據(jù);
 
    init_1602();   //液晶屏初始化;
 
 w_cmd(0x81);  //初始化完成以后先發(fā)送要寫(xiě)入的數(shù)據(jù)的顯示位置.
               //0x81是第一行,第1位. 0x80是第0位;
while(ak[i]!='\0')  //將ak[]數(shù)組內(nèi)的所有數(shù)據(jù)發(fā)送;
  { 
 w_dat(ak[i++]);    //每發(fā)送一個(gè)字節(jié)數(shù)據(jù),數(shù)據(jù)的存儲(chǔ)地址自動(dòng)加一;
 for(s=0;s<50000;s++);  //延時(shí)一下,字符會(huì)有一個(gè),一個(gè)顯示的效果;
    }
w_cmd(0xc1);   //發(fā)送第二排的數(shù)據(jù)地址,接下來(lái)字符會(huì)在第二排第1位開(kāi)始顯示;
i=0;          
while(sj[i]!='\0')   //將sj[]數(shù)組內(nèi)的數(shù)據(jù)全部發(fā)完;
{
  w_dat(sj[i++]);
  for(s=0;s<25000;s++);   //效果延時(shí);

 
}
 
 
while(1);       //死亡循環(huán);

}

關(guān)閉窗口

相關(guān)文章