首先,祝福各位同仁,光棍節(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);
}