×
嵌入式 > 技术百科 > 详情

STM8实现万年历(高亮调时)

发布时间:2021-04-23 发布时间:
|

一、设计内容:


本次设计使用stm8s实现简单的万年历,主要功能是显示时间、调时、设置闹铃。另外还添加了游戏辅助功能。


二、设计要求:


1、主控芯片使用stm8s


2、使用pcb板


3、至少要实现数码管显示时间和调时功能


三、设计过程:


设计总共分为两块,硬件设计和软件设计。首先是构思要实现的功能,然后了解硬件资源再进行软件设计。所以下面首先介绍硬件设计。


1、硬件设计部分


A、元件清单


器件名


型号


数量


Lcd


12864


1


DS1302


1


晶振


32.768KHz


1


Stm8s105s4


1


按键


5


二极管


1n4007


2


电容


220uf


1


10uf


2


104


5


电阻


1k


7


100k


1


10


1


三极管


8550


1


发光led


1


直流蜂鸣器


1


纽扣电池


3v


1


电位器


10k


1


开关


1


电源接口


1


稳压器件


7805


1


B、 原理图


Eda软件使用的是altium designer winter09 ,上面的原理图是从软件中copy出来的。


硬件设计总共分为5个模块。


模块一是电源部分。注意直流电源DC需要9V的电压才能得到5V的稳压输出,因为芯片7805需要一定的电压才能驱动。下面是l7805芯片的额定参数表:


在表中我们可以看到,该芯片的可以承受高达35V的直流电压输入,输出范围是5V-18V。下面还有一张表


从表中我们可以知道,当输入端Ci=0.33uf,C0=104,在输入端给10V直流电时,可以得到最小4.8V的稳压输出。这是该芯片datasheet里面的资料,是最权威的,我们的电源模块也是按照这样接的。


模块二是lcd显示部分。Lcd使用的是12864。12864是一种图形点阵液晶显示器,它主要由行驱动器/列驱动器及128X64全点阵液晶显示器组成,可完成图形显示,也可以显示8X4个(16X16点阵汉字,与外部CPU接口可采用串行或并行方式控制。


模块三是DS1302实时时钟和蜂鸣器。DS1302芯片接的石英晶体是32.768KHz的。另外,接入纽扣电池,实现断电后也可以让DS1302工 作,实现保存时间的功能。蜂鸣器使用的是直流蜂鸣器,用于闹铃提示。直流蜂鸣器内部有个2K的音频驱动源,我们只需加上直流电压就可以让蜂鸣器工作,不 过,使用直流蜂鸣器,我们只能产生一种频率的声音,不过对于闹铃提示来说,已经足够。直流蜂鸣器通过8550PNP管来驱动,主控芯片通过控制8550间 接来控制蜂鸣器。也就是说,io口给出低电平的时候,蜂鸣器就响。这个模块的电阻,主要是用来限流。


模块四是主控芯片。主控芯片使用的stm8s105s4。这块芯片的资源比较丰富。这里只介绍使用的资源。!16M的内部时钟,内部可编程flash rom 达32Kbytes,RAM为2K。44个引脚,有高达38个io端口。多个定时器,我们使用了定时器1。原理图中的两个电容是滤波电容,一个10uf,一个104。用于滤掉高频和低频的干扰。


模块五是按键模块。按键模块用于和用户进行交互。模块中使用了5个按键。电阻为限流电阻。


上面对硬件设计资源进行了概述,我们确定了硬件资源后就开始进行软件设计。


2、软件设计部分


这里使用了模块化编程方法,将各个功能作为一个模块来设计,这样不仅有利于方便的阅读代码,还有利于方便的修改代码和代码的复用等等。


编译器使用的是飞利浦公司提供的免费编译软件ST Visual Develop,该软件主要是用于开发stm系列芯片的。下面是设计的模块截图:


图中显示了各个模块。首先介绍一些配置文件。Stm8s_lib.c实现对主控芯片的硬件配置,主要是初始化主时钟,初始化定时器,初始化io端口和中断 等。设置这个文件为了方便移植和代码复用。相应的stm8s_lib.h是头文件,实现函数的声明。Type.h头文件,实现数据类型的宏定义,也是为了 方便移植和使用。Config.h可以配置一些硬件参数如波特率等等。下面对各个模块进行介绍。


显示模块lcd。文件lcd2864.c是该模块的实现文件,lcd12864.h和lcd_data.h声明了一些与显示相关的数据。具体代码请查看代码附件。


这里我们来看lcd12864.h这个头文件。这里面是12864的驱动函数。


void LcdInit(void);//初始化lcd


void WCmd(uchar cmd); //向显示控制器写命令


void WData(uchar ch); //向显示控制器写数据


uchar RBBF(void); //读忙标志


uchar RData(void); //读数据,由于没有使用到,这里代码不完整


uchar RByte(uchar addr);//读一个字节


void WByte(uchar addr,uchar buf);//写一个字节


//在屏幕上显示数据参数为(地址,数据buffer,汉字数)


void showword(uchar addr,uchar *buf,uchar count);//在屏幕上


//在屏幕上显示数据参数为(地址,数据buffer,字节数)


void showbyte(uchar addr,uchar *buf,uchar count);


//显示选择光标 falg=1 为显示


void ShowCur(uchar flag);


//清屏


void Clear_Screen(uchar addr,uchar count);


void Clear_all(void);


//将模式设置为显示像素点


void Set_Draw(uchar flag);


//高亮显示,参数为(横坐标0-15,纵坐标0-3,显示标志1为显示字符)


//2为显示汉字,3为清除高亮显示,以字的方式。


void High_Show(uchar x,uchar y,uchar flag);


//清除CGROM,将rom写0,避免花屏


void Clear_CGRom(void);


//图像显示初始化


void CG_init(void);


//恢复普通显示


Void CG_leave(void);


这里需要注意延时,给足够的时间显示控制器处理指令。我们主要使用showword函数来显示内容,ShowCur函数用来显示光标,提示用户当前选择。下面是时间显示的显示界面。注意左下角的就是光标。


实时时钟模块。实时时钟模块文件是DS1302.c,头文件是ds1302.h.


展开ds1302.h我们可以看到:


void ds1302_init(void);//ds1302初始化


void Read_Time(void); //读时间


void write_ds1302_com(uchar com);//写命令


void write_ds1302_data(uchar addr,uchar dat);//写数据


uchar read_ds1302_data(uchar addr);//读数据


void set_time(void);//设置时间


void read_time(void);//读时间


void translate(void);//转换时间


我们主要使用ds1302_init来初始化时钟芯片,Read_Time来读取时间,set_time来设置时间。


Uart.c文件模块。这个文件主要是实现串口通信的。在uart.h文件中:


void InitUART2(void); //初始化


void Uart_SendByte(unsigned char ch);//发送一个字节


void Uart_SendString(char *pt); //发送字符串


主要使用Uart_SendString这个函数,用于程序的调试。最终硬件实现是不添加串口通信功能的。所以关于串口通信的代码全部使用宏定义,在调试完成后,去掉宏定义就可以去除串口通信相关的代码了。


现在介绍main.c这个文件。这个主文件,将各个模块的接口连接起来,最终显示我们想要的功能。首先,也是必须的,我们来看看添加到main.c的头文件。


#include "stm8s105s4.h" //芯片头文件


#include "stm8s_lib.h" //这里就调用了配置函数


#include "lcd12864.h" //调用lcd驱动


#include "UART.h" //串口通信


#include "ds1302.h" //实时时钟的调用


#include "type.h" //类型定义


#include "lcd_data.h" //lcd显示数据


#include "beep_data.h" //蜂鸣器数据


有了上面的头文件,就可以实现相应的功能了。


这里我们将按键扫面驱动写在了主文件当中。使用定时器1产生20ms的定时器中断,实现按键扫描。代码如下:


@far @interrupt void TIM1_KEY (void)


{


//////////////////////////////////


TIM1_SR1=0X00;


if(time_counter>0)


{


time_counter--;


if(time_counter==0)


{


BEEP=1;


TIM3_CR1=0x00; //关闭计数


}


Ring_Beep();


}


/////////////////////按键扫描//////////////////////////


if(!KeyCanChange) //按键处理中标志位


return;


KeyCurrent=GetKeyValue();//获得当前键值 ,若没有按键按下 为高,


if(KeyCurrent!=KeyOld) //这里开始按键计时,若按键不同就使 KeyNoChangedTime为0,开始计数按键按下时间


{ //这里判断是否按键改变


KeyNoChangedTime=0;


KeyOld=KeyCurrent;


return;


}


else


{


KeyNoChangedTime++; //按键计时


if(KeyNoChangedTime>=1) //若按键按下时间足够,


{


KeyNoChangedTime=1;


KeyPress=KeyOld; //就保存该键值


KeyDown|=(~KeyLast)&(KeyPress); //按键为0 这里指定位置1,表示该键被按下


KeyUp|=KeyLast&(~KeyPress); //按键为 指定位置1,表示上次按键松开


KeyLast=KeyPress;


}


}


}


这个按键扫描驱动比较强大。可以感应按键的按下和松开。去抖动性能比较好。


现在介绍main函数,硬件启动后,执行到main函数,我们在main函数中实现硬件的初始化,外围芯片的初始化。然后显示启动画面。之后进入主菜单页面。Menu_show函数用于显示主菜单。界面为


-----------------------------------


-》万年历


闹钟设置


调整时间


游戏


---------------------------------------------------------------


然后就是进行菜单的选择。下面进行菜单介绍:


万年历。进入这个菜单后,主要就是读取DS1302的时间,并使用lcd显示出来。


闹铃设置。这里面将数据存在EEPROM中,每次进入万年历菜单和本菜单后,就将EEPROM中的数据读出,用于修改和比较。界面如下:


-----------------------------


闹铃设置


00:00:00


----------------------------------


调整时间。主要是对ds1302进行操作,设置时间。


游戏。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
激光跟踪仪市场2023年有望达5.216亿美元