當(dāng)前位置:首頁(yè) > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]一.原理和功能介紹1.PROTEUS模擬的效果圖如下:我簡(jiǎn)要介紹一下系統(tǒng)的組成及各部分的功能本系統(tǒng)主要有五部分構(gòu)成:1.顯示和鍵盤顯示采用的是最常用最便宜的1602液晶,內(nèi)藏HD44780,且內(nèi)含簡(jiǎn)單字庫(kù).指令簡(jiǎn)單,容易上手鍵盤部

一.原理和功能介紹

1.PROTEUS模擬的效果圖如下:

我簡(jiǎn)要介紹一下系統(tǒng)的組成及各部分的功能

本系統(tǒng)主要有五部分構(gòu)成:

1.顯示和鍵盤

顯示采用的是最常用最便宜的1602液晶,內(nèi)藏HD44780,且內(nèi)含簡(jiǎn)單字庫(kù).指令簡(jiǎn)單,容易上手

鍵盤部分由7個(gè)按鍵和一個(gè)電位器旋鈕組成系統(tǒng)的輸入部分.(如圖)

2.運(yùn)算處理單元

本系統(tǒng)的所有操作都由PIC16F877A單片機(jī)完成(選擇他的理由:端口多,不需擴(kuò)展)

3.存儲(chǔ)單元

主要由一片24C01的1K內(nèi)存的EEPROM完成,此芯片與單片機(jī)通過I2C總線通信,具有占有端口少的優(yōu)點(diǎn).

4.輸出控制單元

由一片光耦和一個(gè)雙向晶閘管組成.單片機(jī)輸出的脈沖通過控制光耦的通斷控制雙向晶閘管的通斷,從而控制電燈的亮度.

5.時(shí)鐘單元

這是一個(gè)附加單元,對(duì)本系統(tǒng)無關(guān)鍵作用,只是為了增加附加值.有一片DS1302時(shí)鐘芯片和一個(gè)32768Hz的晶振組成

功能說明

1.一上電,系統(tǒng)顯示"ADJUST"可調(diào)狀態(tài),此時(shí)旋鈕調(diào)節(jié)光的亮度,即PWM波的占空比,如果此時(shí)按下"存儲(chǔ)"鍵,則此時(shí)的亮度值被記錄下來并保存,共可以記錄下三個(gè)不同的亮度.

2.如你按下"模式"鍵,此時(shí)旋鈕被屏蔽,只能調(diào)用你存儲(chǔ)的三個(gè)亮度值,分別為"MODE 1","MODE 2","MODE 3"方便你的使用.

3.時(shí)間設(shè)置的兩個(gè)按鍵可以實(shí)時(shí)調(diào)整時(shí)間.

二.程序(picc 8.05)

1.主程序

/***************************************************************
* 標(biāo)題:PWM輸出 *
* 作者:Wujieflash *
* 日期:2008年1月25日 *
* 功能:使用PIC的CCP模塊輸出PWM波 *
***************************************************************/
#include
#include "LCD1602_init.h"
#include "ds1302.h"
#include "i2c.h"

static volatile bitGODONE@ ((unsigned)&ADCON0*8)+2;
uch k,kb,kmem;
void PWMinit()
{
TRISC=0xfb;//設(shè)置C口狀態(tài)
PORTC=0x00;
PR2=0xff; //設(shè)置PWM波的周期
CCP1CON=0x0c;
CCPR1L=0x1c;//設(shè)置占空比

T2CON=0x01; //設(shè)置1:4預(yù)分頻
TMR2ON=1; //開啟定時(shí)器2
}
/*-------------------------------------------------------*/

void AD_convert_init() //旋鈕采樣輸出
{
uch i;
ADCON1=0x00;
ADCON0=0x01;
for(i=0;i<100;i++);
GODONE=1;
}
/*-------------------------------------------------------*/

void ADScan()
{

if(GODONE==0)
{
if(ADRESH>0xe3)ADRESH=0xe3; //限制占空比的范圍
if(ADRESH<0x1c)ADRESH=0x1c;
CCPR1L=ADRESH;
GODONE=1;

}
}
/*-------------------------------------------------------*/

void KeyScan() //設(shè)置時(shí)間子程序
{
int d;

if(RC6==0) //設(shè)置鍵按下
{
k++; //選定入口值
k=k%3;
}
while(1)
{
if(RC6==1)break;//等待按鍵松開
}
switch(k)//鍵盤服務(wù)入口
{
case 1://設(shè)置分
{
d=R1302(0x83);//讀取分
d=d/16*10+d%16;//轉(zhuǎn)換為16進(jìn)制
minute=flag; //設(shè)置秒的閃爍標(biāo)志
hour=1; //其余變量不閃爍

if(minute==0) //閃爍
{
WriteCommand_1602(0xce);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
if(RC7==0) //分?jǐn)?shù)值加1
{
d++;
if(d>0x3b)d=0;//大于59就為0
d=d/10*16+d%10;
W1302(0x82,d);//寫入DS1302
while(1)
{
if(RC7==1)break;//等待鍵松開
}
}
break;
}
case 2://設(shè)置時(shí)
{
d=R1302(0x85);//讀取時(shí)
d=d/16*10+d%16;//轉(zhuǎn)換為16進(jìn)制
hour=flag; //設(shè)置秒的閃爍標(biāo)志
minute=1; //其余變量不閃爍

if(hour==0) //閃爍
{
WriteCommand_1602(0xcb);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
if(RC7==0) //時(shí)數(shù)值加1
{
d++;
if(d>0x17)d=0;//大于59就為0
d=d/10*16+d%10;
W1302(0x84,d);//寫入DS1302
while(1)
{
if(RC7==1)break;//等待鍵松開
}
}
break;
}
case 0://設(shè)置完畢,不閃爍
{
minute=1;
hour=1;
break;
}
}
}
/*-------------------------------------------------------*/

void KeyScan1() //輸出顯示子程序
{
if(RC0==0) //模式鍵
{
kb++;
kb=kb%2;
}
while(1)
{
if(RC0==1)break;
}
switch(kb)
{
case 0: //可調(diào)模式,
{
ADON=1;//旋鈕有效
WriteCommand_1602(0x80);
WriteData_1602('A');
WriteData_1602('D');
WriteData_1602('J');
WriteData_1602('U');
WriteData_1602('S');
WriteData_1602('T');
WriteCommand_1602(0x8a);
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);

if(RC5==0) //存儲(chǔ)鍵
{
kmem++;
kmem=kmem%3;
while(1)
{
if(RC5==1)break;
}
switch(kmem)
{
case 1:
{
w_24cl01b(0x00,ADRESH); //寫入第一通道
WriteCommand_1602(0x8a);
WriteData_1602('C');
WriteData_1602('H');
WriteData_1602('1');
WriteData_1602(0x00);
WriteData_1602('O');
WriteData_1602('K');
break;
}
case 2:
{
w_24cl01b(0x01,ADRESH); //寫入第二通道
WriteCommand_1602(0x8a);
WriteData_1602('C');
WriteData_1602('H');
WriteData_1602('2');
WriteData_1602(0x00);
WriteData_1602('O');
WriteData_1602('K');
break;
}
case 0:
{
w_24cl01b(0x02,ADRESH); //寫入第三通道
WriteCommand_1602(0x8a);
WriteData_1602('C');
WriteData_1602('H');
WriteData_1602('3');
WriteData_1602(0x00);
WriteData_1602('O');
WriteData_1602('K');
break;
}
}
}
break;
}
case 1: //"MODE"模式
{
ADON=0; //屏蔽旋鈕
WriteCommand_1602(0x80);
WriteData_1602('M');
WriteData_1602('O');
WriteData_1602('D');
WriteData_1602('E');
WriteData_1602(0x0);
WriteData_1602(0x0);

if(RC1==0) //模式一
{
CCPR1L=r_24cl01b(0x00);
ADRESH=r_24cl01b(0x00);
while(1)
{
if(RC1==1)break;
}
WriteCommand_1602(0x8a);
WriteData_1602('C');
WriteData_1602('H');
WriteData_1602('1');
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
if(RC3==0) //模式二
{
CCPR1L=r_24cl01b(0x01);
ADRESH=r_24cl01b(0x01);
while(1)
{
if(RC3==1)break;
}
WriteCommand_1602(0x8a);
WriteData_1602('C');
WriteData_1602('H');
WriteData_1602('2');
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
if(RC4==0) //模式三
{
CCPR1L=r_24cl01b(0x02);
ADRESH=r_24cl01b(0x02);
while(1)
{
if(RC4==1)break;
}
WriteCommand_1602(0x8a);
WriteData_1602('C');
WriteData_1602('H');
WriteData_1602('3');
WriteData_1602(0x00);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
break;
}
}
}
/*-------------------------------------------------------*/

void DisplaySet(uch val) //顯示占空比子程序
{
int pwm,pwm_shi,pwm_ge;
if(val>0xe3)val=0xe3;
if(val<0x1c)val=0x1c;
pwm=val*100/255;
pwm_shi=0x30+pwm/10;
pwm_ge=0x30+pwm%10;
WriteCommand_1602(0xc4);
WriteData_1602(pwm_shi);
WriteData_1602(pwm_ge);
WriteData_1602('%');
}
/*-------------------------------------------------------*/

void main()
{
init1602();
i2c_init();
AD_convert_init();
TMR1init();
PWMinit();
while(1)
{
ADScan();
DisplaySet(ADRESH);
FlashMaohao();
DisplayTime1602();
KeyScan();
KeyScan1();
}
}
2.I2C子程序

/***************************************************************
* 標(biāo)題:I2C協(xié)議 *
* 作者:Wujieflash *
* 日期:2008年2月2日 *
* 功能:I2C通訊協(xié)議 *
***************************************************************/
#define nop() asm("nop")
#define SCL RD6
#define SDA RD7

void i2c_init()
{
TRISD6=0;
TRISD7=0;
RD6=0;
RD7=0;
}
/*------------------------------------------------------------------*/
//start
void start_iic()
{
SDA=1;
nop();
nop();
SCL=1;
nop();
nop();
nop();
nop();
SDA=0;
nop();
nop();
SCL=0;//it is ready to send data
nop();
}
/*------------------------------------------------------------------*/
//stop
void stop_iic(void)
{
SDA=0;
nop();
nop();
SCL=1;
nop();
nop();
nop();
nop();
SDA=1;
nop();
}
/*------------------------------------------------------------------*/
//send ack
void ack_iic()
{
SDA=0;
nop();
nop();
SCL=1;
nop();
nop();
nop();
nop();
SCL=0;
nop();
nop();
}
/*------------------------------------------------------------------*/
//send nack
void nack_iic()
{
SDA=1;
nop();
nop();
SCL=1;
nop();
nop();
nop();
nop();
SCL=0;
nop();
nop();
}
/*------------------------------------------------------------------*/
//send 1 byte
void send_iic(char c)
{
uch i;
for(i=0;i<8;i++)
{
SCL=0;
if((c<{
SDA=1;
}
else
{
SDA=0;
}
SCL=1;
nop();
nop();
nop();
nop();
SCL=0;
nop();
}
SDA=1;
TRISD7=1;
SCL=1;
nop();
nop();
nop();
nop();
SCL=0;
nop();
TRISD7=0;
}
/*------------------------------------------------------------------*/
//receive 1 byte
uch receive_iic(void)
{
uch rxbuf=0;
uch i;
//SDA=1;

TRISD7=1;
for(i=0;i<8;i++)
{
SCL=0;
nop();
nop();
nop();
nop();
nop();
SCL=1;
nop();
nop();
rxbuf=rxbuf<<1;
if(SDA==1)
{
rxbuf=rxbuf+1;
}
nop();
nop();
}

SCL=0;
nop();
TRISD7=0;
return(rxbuf);
}
/*------------------------------------------------------------------*/
//write 24cl01b subroutine
void w_24cl01b(unsigned char addr,unsigned char data)
{
int i;
start_iic();
send_iic(0xa0);
send_iic(addr);
send_iic(data);
stop_iic();
for(i=0;i<500;i++);
}
/*------------------------------------------------------------------*/
//read 24cl01b subroutine
char r_24cl01b(unsigned char addr)
{
int i;
uch data;
start_iic();
send_iic(0xa0);
send_iic(addr);

start_iic();
send_iic(0xa1);

data=receive_iic();
nack_iic();
stop_iic();
for(i=0;i<1000;i++);
return(data);
}

3.1602操作子程序

/***************************************************************
* 標(biāo)題:LCD1602驅(qū)動(dòng) *
* 作者:Wujieflash *
* 日期:2008年1月29日 *
* 功能:驅(qū)動(dòng)1602液晶的驅(qū)動(dòng)程序 *
***************************************************************/
#include

#define RS RD0
#define RW RD1
#define E RD2

#define uch unsigned char

//延時(shí)子程序
void delay_1602(int time)
{
while(time--);
}
/*-----------------------------------------------*/

//寫命令子程序
void WriteCommand_1602(uch command)
{
RS=0;
RW=0;

delay_1602(400);
E=1;
PORTB=command;
E=0;
}
/*-----------------------------------------------*/

//寫數(shù)據(jù)子程序
void WriteData_1602(uch data)
{
RS=1;
RW=0;

delay_1602(400);
E=1;
PORTB=data;
E=0;
}
/*-----------------------------------------------*/

//初始化LCD1602子程序
void init1602()
{
TRISD0=0;
TRISD1=0;
TRISD2=0;
RD0=0;
RD1=0;
RD2=0;
TRISB=0;
PORTB=0;
WriteCommand_1602(0x01);
WriteCommand_1602(0x38);
WriteCommand_1602(0x0c);
WriteCommand_1602(0x80);
//WriteData_1602('M');
//WriteData_1602('O');
//WriteData_1602('D');
//WriteData_1602('E');
//WriteData_1602(':');
WriteCommand_1602(0xc0);
WriteData_1602('P');
WriteData_1602('W');
WriteData_1602('M');
WriteData_1602(':');
}
4.時(shí)鐘子程序

/***************************************************************
* 標(biāo)題:DS1302數(shù)字時(shí)鐘 *
* 作者:Wujieflash *
* 日期:2008年1月29日 *
* 功能:顯示日歷與時(shí)間的程序 *
***************************************************************/
#define RST RD3
#define SCLK RD4
#define IO RD5
uch flag=0;
uch minute=1,hour=1;
uch clock[]={0};
uch DisCash[]={0x00,0x30,0x09,0x16,0x01,0x03,0x09};
/////往1302寫入1Byte數(shù)據(jù)////////////////////////
void RTInputByte(uch d)
{
uch i;
TRISD3=0;
TRISD4=0;
TRISD5=0;
for(i=8; i>0; i--)
{
IO = d&0x01; //取最低位
SCLK = 1; //上升沿發(fā)送
SCLK = 0; //恢復(fù)
d = d >> 1;
}
}
///////從1302讀取1Byte數(shù)據(jù)////////////////////////
uch RTOutputByte(void)
{
uch i,val=0;
TRISD5=1; //設(shè)置為輸入
for(i=8; i>0; i--)
{
val = val >>1;
if(IO)val=val|0x80;// 從最低位開始接收
SCLK = 1; //下降沿接收
SCLK = 0;
}
TRISD5=0;
return(val);
}
///////先寫地址,后寫命令/數(shù)據(jù)//////////////////////////
void W1302(uch ucAddr, uch ucDa)
{
RST = 0;
SCLK = 0;
RST = 1; //打開DS1302
RTInputByte(ucAddr); // /* 地址,命令 */
RTInputByte(ucDa); // /* 寫1Byte數(shù)據(jù)*/
SCLK = 1;
RST = 0; //關(guān)閉DS1302
}
///////先寫地址,后讀命令/數(shù)據(jù)////////////////////////
uch R1302(uch ucAddr)
{
uch ucData;
RST = 0;
SCLK = 0;
RST = 1;
RTInputByte(ucAddr); // /* 地址,命令 */
ucData = RTOutputByte(); // /* 讀1Byte數(shù)據(jù) */
SCLK = 1;
RST = 0;
return(ucData);
}
/////////向1302寫入 秒 分 時(shí) 日 月 星期 年 */////////////
void Set1302(uch *pClock)
{
uch i;
uch ucAddr = 0x80; //起使地址
W1302(0x8e,0x00); ///* 控制命令,WP=0,允許寫操作*/
for(i =7; i>0; i--)
{
W1302(ucAddr,*pClock); ///* 秒 分 時(shí) 日 月 星期 年 */
pClock++;
ucAddr +=2; //寫地址加2
}
W1302(0x8e,0x80); // /* 控制命令,WP=1,寫保護(hù)*/
}
////////從1302讀出 秒 分 時(shí) 日 月 星期 年 *//////////////////
void v_Get1302(unsigned char ucCurtime[])
{
unsigned char i;
unsigned char ucAddr = 0x81;
for(i=0;i<7;i++)
{
ucCurtime[i] = R1302(ucAddr);///*格式為: 秒 分 時(shí) 日 月 星期 年 */
ucAddr += 2;
}
}

//使用LCD1602顯示
void DisplayTime1602()
{
uch hour_shi,hour_ge,minute_shi,minute_ge;
v_Get1302(clock);
hour_shi=0x30+clock[2]/16;
hour_ge=0x30+clock[2]%16;
minute_shi=0x30+clock[1]/16;
minute_ge=0x30+clock[1]%16;

if(hour==1)
{WriteCommand_1602(0x80+0x4b);
WriteData_1602(hour_shi);
WriteData_1602(hour_ge);
}

if(minute==1)
{WriteCommand_1602(0x80+0x4e);
WriteData_1602(minute_shi);
WriteData_1602(minute_ge);
}
}
//TRM1初始化子程序
void TMR1init()
{
//TRM1 INITIAL
T1CON=0X30; //8分頻
TMR1IF=0; //清中斷標(biāo)志
TMR1IE=1; //使能定時(shí)器1中斷
TMR1L=0XDB; //初始值(定時(shí)0.5S)
TMR1H=0X0B;
TMR1ON=1; //開定時(shí)器1
}

//冒號(hào)閃爍子程序
void FlashMaohao()
{
if(TMR1IF==1)
{
TMR1ON=0;
TMR1IF=0;
TMR1L=0XDB; //重新付初值
TMR1H=0X0B;
flag++;
flag=flag%2; //閃爍標(biāo)志在0-1間翻轉(zhuǎn)
TMR1ON=1;
}
if(flag==0)
{
WriteCommand_1602(0xcd);
WriteData_1602(':');
}
if(flag==1)
{
WriteCommand_1602(0xcd);
WriteData_1602(0x00);
}
}

三.總結(jié)

雖然是完成了,但還有很多遺憾:

1.并沒有完全仿真出來,主要由于軟件需要的數(shù)字和模擬器件太多,資源太多,運(yùn)行不過來.

2.有些實(shí)物已經(jīng)驗(yàn)證的程序在PROTEUS上卻失敗,如24C01能寫入,卻讀出來總為0,事實(shí)卻可以的.

3.程序邏輯性還是差了點(diǎn),感覺很混亂.

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉