当前位置:首页 > 单片机 > 单片机
[导读]一.原理和功能介绍1.PROTEUS模拟的效果图如下:我简要介绍一下系统的组成及各部分的功能本系统主要有五部分构成:1.显示和键盘显示采用的是最常用最便宜的1602液晶,内藏HD44780,且内含简单字库.指令简单,容易上手键盘部

一.原理和功能介绍

1.PROTEUS模拟的效果图如下:

我简要介绍一下系统的组成及各部分的功能

本系统主要有五部分构成:

1.显示和键盘

显示采用的是最常用最便宜的1602液晶,内藏HD44780,且内含简单字库.指令简单,容易上手

键盘部分由7个按键和一个电位器旋钮组成系统的输入部分.(如图)

2.运算处理单元

本系统的所有操作都由PIC16F877A单片机完成(选择他的理由:端口多,不需扩展)

3.存储单元

主要由一片24C01的1K内存的EEPROM完成,此芯片与单片机通过I2C总线通信,具有占有端口少的优点.

4.输出控制单元

由一片光耦和一个双向晶闸管组成.单片机输出的脉冲通过控制光耦的通断控制双向晶闸管的通断,从而控制电灯的亮度.

5.时钟单元

这是一个附加单元,对本系统无关键作用,只是为了增加附加值.有一片DS1302时钟芯片和一个32768Hz的晶振组成

功能说明

1.一上电,系统显示"ADJUST"可调状态,此时旋钮调节光的亮度,即PWM波的占空比,如果此时按下"存储"键,则此时的亮度值被记录下来并保存,共可以记录下三个不同的亮度.

2.如你按下"模式"键,此时旋钮被屏蔽,只能调用你存储的三个亮度值,分别为"MODE 1","MODE 2","MODE 3"方便你的使用.

3.时间设置的两个按键可以实时调整时间.

二.程序(picc 8.05)

1.主程序

/***************************************************************
* 标题: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;//设置C口状态
PORTC=0x00;
PR2=0xff; //设置PWM波的周期
CCP1CON=0x0c;
CCPR1L=0x1c;//设置占空比

T2CON=0x01; //设置1:4预分频
TMR2ON=1; //开启定时器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() //设置时间子程序
{
int d;

if(RC6==0) //设置键按下
{
k++; //选定入口值
k=k%3;
}
while(1)
{
if(RC6==1)break;//等待按键松开
}
switch(k)//键盘服务入口
{
case 1://设置分
{
d=R1302(0x83);//读取分
d=d/16*10+d%16;//转换为16进制
minute=flag; //设置秒的闪烁标志
hour=1; //其余变量不闪烁

if(minute==0) //闪烁
{
WriteCommand_1602(0xce);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
if(RC7==0) //分数值加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://设置时
{
d=R1302(0x85);//读取时
d=d/16*10+d%16;//转换为16进制
hour=flag; //设置秒的闪烁标志
minute=1; //其余变量不闪烁

if(hour==0) //闪烁
{
WriteCommand_1602(0xcb);
WriteData_1602(0x00);
WriteData_1602(0x00);
}
if(RC7==0) //时数值加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://设置完毕,不闪烁
{
minute=1;
hour=1;
break;
}
}
}
/*-------------------------------------------------------*/

void KeyScan1() //输出显示子程序
{
if(RC0==0) //模式键
{
kb++;
kb=kb%2;
}
while(1)
{
if(RC0==1)break;
}
switch(kb)
{
case 0: //可调模式,
{
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) //存储键
{
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子程序

/***************************************************************
* 标题:I2C协议 *
* 作者:Wujieflash *
* 日期:2008年2月2日 *
* 功能:I2C通讯协议 *
***************************************************************/
#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操作子程序

/***************************************************************
* 标题:LCD1602驱动 *
* 作者:Wujieflash *
* 日期:2008年1月29日 *
* 功能:驱动1602液晶的驱动程序 *
***************************************************************/
#include

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

#define uch unsigned char

//延时子程序
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;
}
/*-----------------------------------------------*/

//写数据子程序
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.时钟子程序

/***************************************************************
* 标题:DS1302数字时钟 *
* 作者:Wujieflash *
* 日期:2008年1月29日 *
* 功能:显示日历与时间的程序 *
***************************************************************/
#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数据////////////////////////
void RTInputByte(uch d)
{
uch i;
TRISD3=0;
TRISD4=0;
TRISD5=0;
for(i=8; i>0; i--)
{
IO = d&0x01; //取最低位
SCLK = 1; //上升沿发送
SCLK = 0; //恢复
d = d >> 1;
}
}
///////从1302读取1Byte数据////////////////////////
uch RTOutputByte(void)
{
uch i,val=0;
TRISD5=1; //设置为输入
for(i=8; i>0; i--)
{
val = val >>1;
if(IO)val=val|0x80;// 从最低位开始接收
SCLK = 1; //下降沿接收
SCLK = 0;
}
TRISD5=0;
return(val);
}
///////先写地址,后写命令/数据//////////////////////////
void W1302(uch ucAddr, uch ucDa)
{
RST = 0;
SCLK = 0;
RST = 1; //打开DS1302
RTInputByte(ucAddr); // /* 地址,命令 */
RTInputByte(ucDa); // /* 写1Byte数据*/
SCLK = 1;
RST = 0; //关闭DS1302
}
///////先写地址,后读命令/数据////////////////////////
uch R1302(uch ucAddr)
{
uch ucData;
RST = 0;
SCLK = 0;
RST = 1;
RTInputByte(ucAddr); // /* 地址,命令 */
ucData = RTOutputByte(); // /* 读1Byte数据 */
SCLK = 1;
RST = 0;
return(ucData);
}
/////////向1302写入 秒 分 时 日 月 星期 年 */////////////
void Set1302(uch *pClock)
{
uch i;
uch ucAddr = 0x80; //起使地址
W1302(0x8e,0x00); ///* 控制命令,WP=0,允许写操作*/
for(i =7; i>0; i--)
{
W1302(ucAddr,*pClock); ///* 秒 分 时 日 月 星期 年 */
pClock++;
ucAddr +=2; //写地址加2
}
W1302(0x8e,0x80); // /* 控制命令,WP=1,写保护*/
}
////////从1302读出 秒 分 时 日 月 星期 年 *//////////////////
void v_Get1302(unsigned char ucCurtime[])
{
unsigned char i;
unsigned char ucAddr = 0x81;
for(i=0;i<7;i++)
{
ucCurtime[i] = R1302(ucAddr);///*格式为: 秒 分 时 日 月 星期 年 */
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; //清中断标志
TMR1IE=1; //使能定时器1中断
TMR1L=0XDB; //初始值(定时0.5S)
TMR1H=0X0B;
TMR1ON=1; //开定时器1
}

//冒号闪烁子程序
void FlashMaohao()
{
if(TMR1IF==1)
{
TMR1ON=0;
TMR1IF=0;
TMR1L=0XDB; //重新付初值
TMR1H=0X0B;
flag++;
flag=flag%2; //闪烁标志在0-1间翻转
TMR1ON=1;
}
if(flag==0)
{
WriteCommand_1602(0xcd);
WriteData_1602(':');
}
if(flag==1)
{
WriteCommand_1602(0xcd);
WriteData_1602(0x00);
}
}

三.总结

虽然是完成了,但还有很多遗憾:

1.并没有完全仿真出来,主要由于软件需要的数字和模拟器件太多,资源太多,运行不过来.

2.有些实物已经验证的程序在PROTEUS上却失败,如24C01能写入,却读出来总为0,事实却可以的.

3.程序逻辑性还是差了点,感觉很混乱.

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭