液晶时钟,时间可通过串口修改
main.c
/*----------------------C语言示例-----------------------*
*硬件连接:PTB-HD44780data,PTC0-RS,PTC1-RW,PTC2-E *
*程序描述: 1.以串行中断方式接收从PC机发送来的时钟启 *
* 动信号56H和时间值 *
* v11:11:11:11表示11:11:11 *
* 2.以定时中断方式实现实现1秒的定时 *
* 3.以串行接受中断方式接受从PC机发送来的时 *
* 钟停止信号57H并向PC方发送当前的时钟数据 *
*使用模块: 定时模块、串行通信模块及LCD模块 *
*作者: 刘玉宏 *
*版本 V1.0 *
*修改日期: 2005-6-11 *
*------------------------------------------------------*/
#define main_c
#include "main.h" //本模块头文件
#include "lcd.h" //其它模块头文件
#include "interrupt.h" //其它模块头文件
//---------------主程序全局变量定义--------------------
unsigned char time[9]= "12:00:00";
const unsigned char info[17]= "HoHai university";
//----------------------------------------------------
void main(void)
{
DisableInterrupts; //禁止所有中断
init_con(); //系统初始化
DDRA=0xff; //I/O初始化
DDRB=0xff;
DDRC=0x17;
init_timer1(); //定时器1初始化
init_sci(); //[SCI初始化]
Init_HD44780(0b00111100); //LCD初始化
print1L(time); //显示时间初值
print2L(info); //显示其它信息
EnableInterrupts; //开中断
for(;;){
};
}
//===================================================================
//= 函数原型: void init_con(void)
//= 功 能: 系统配置及时钟初始化
//= 参 数: 无
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void init_con(void)
{
}
//===================================================================
//= 函数原型: void init_timer1(void)
//= 功 能: 初始化定时器1
//= 参 数: 无
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void init_timer1(void)
{
T1SC=0b01100110; //01100110允许溢出中断、
//不启动计数、分频因子=64
T1CNTH=0; //计数器初值清0
T1CNTL=0;
T1MODH=0x96; //设1秒产生1次溢出中断
T1MODL=0; //模数寄存器设定值=
//1×(2457600/64)=$9600
}
//===================================================================
//= 函数原型: void init_sci(void)
//= 功 能: 初始化串口
//= 参 数: 无
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void init_sci(void)
{
//监控程序已初始化一部分
SCC2=0x2c; //设置接收中断允许
}
main.h
#ifndef main_h //防止在同一模块多次包含
#define main_h
#include "head.h" //本工程公共头文件
#include <hidef.h> //系统头文件,包含开关中断
#include <MC68HC908GP32.h> //芯片头文件
#ifndef main_c
//*********主程序非静态全局变量定义*************
extern unsigned char time[];
extern const unsigned char info[];
//自己模块内的全局变量,公共函数声明给其他模块
#else
//*********主程序自定义函数说明***
void init_con(void);
void init_timer1(void);
void init_sci(void);
//自己的私有函数和公共函数声明给自己模块
#endif
#endif
lcd.c
#define lcd_c
#include "main.h" //其它模块头文件
#include "lcd.h" //本模块头文件
#include "interrupt.h" //其它模块头文件
//===================================================================
//= 函数原型: void DelaySub(INT16U i,INT16U vector)
//= 功 能: 延时函数
//= 参 数: 为延时大小,vector为延时矢量
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void DelaySub(INT16U i,INT16U vector)
{
INT16U j;
INT16U x;
for(j=0;j<=i;j++)
for(x=0;x<=vector;x++);
}
//===================================================================
//= 函数原型: void AsmDelay(INT8U delaytime)
//= 功 能: 延时函数
//= 参 数: 为延时大小
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void AsmDelay(INT8U delaytime)
{
while(delaytime--) {
asm("NOP"); //1 cycles
asm("NOP"); //1 cycles
}
}
//===================================================================
//= 函数原型: void LCD_Command(INT8U cmd)
//= 功 能: 对A中指令使用PORTB作为输出口,
// 到LCD进行命令执行或字符显示
//= 参 数: cmd,执行的指令,8位
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void LCD_Command(INT8U cmd)
{
AsmDelay(15); //等待约40us
PTB=cmd; //把指令码送到B口
asm("NOP");
asm("NOP");
PTC|=0b00000100; //LCD开始接受数据,置使能位为1
asm("NOP");
asm("NOP");
PTC&=0b11111011; //LCD结束接受数据,置使能位为0
AsmDelay(15); //等待约40us
}
//===================================================================
//= 函数原型: void Init_HD44780(INT8U setting)
//= 功 能: 初始化HD44780
//= 参 数: "HD44780功能"设置命令
//= 返 回 值: 无
//= 函数性质:公有函数
//===================================================================
void Init_HD44780(INT8U setting)
{
PTC&=0b11111110; //令LCD的RS=0,R/W=0,
//进行LCD初始化
PTC&=0b11111101;
//功能设置:数据接口,显示行数,点阵模式
//00111000:8位数据接口,2行显示,5*7点阵模式
//00110100:8位数据接口,1行显示,5*10点阵模式
LCD_Command(setting);
//显示开关控制:关显示,关光标显示,不闪烁
LCD_Command(0b00001000);
AsmDelay(15); //等待约40us
PTC&=0b11111110; //RS,RW清零开始清屏
PTC&=0b11111101;
LCD_Command(0b00000001); //清屏指令
DelaySub(1,0x200); //等待清屏完毕,时间>1.6ms
//输入方式设置:数据读写操作后,
//AC自动增1显示不动,光标左移
LCD_Command(0b00000110);
//光标移位设置:光标右移一个字符位,AC自动加1
LCD_Command(0b00010100);
//显示开关设置:开显示,关光标显示,不闪烁
LCD_Command(0b00001100);
}
//===================================================================
//= 函数原型: void print1L(INT8U *s)
//= 功 能: HD44780第一行显示
//= 参 数: 欲显示的字符串
//= 返 回 值: 无
//= 函数性质:公有函数
//===================================================================
void print1L(INT8U *s)
{
INT8U i;
i=0;
PTC&=0b11111110;
PTC&=0b11111101;
LCD_Command(0b10000000);
while(*s&&i<16){
PTC|=0b00000001; //令LCD的RS=1,R/W=0,
//写入数据到DD RAM中
PTC&=0b11111101;
LCD_Command(*s); //将要显示的字符串
//分个送到LCD
s++;
i++;
}
}
//===================================================================
//= 函数原型: void print2L(INT8U *s)
//= 功 能: HD44780第二行显示
//= 参 数: 欲显示的字符串
//= 返 回 值: 无
//= 函数性质:公有函数
//===================================================================
void print2L(INT8U *info)
{
INT8U i;
i=0;
PTC&=0b11111110;
PTC&=0b11111101;
LCD_Command(0b11000000);
i=0;
//如果超过16个字符,将字符全部送完
while(info[i]&&i<16){
PTC|=0b00000001; //令LCD的RS=1,R/W=0,
//写入数据到DD RAM中
PTC&=0b11111101;
LCD_Command(info[i]);
i++;
}
}
lcd.h
#ifndef lcd_h //防止在同一模块多次包含
#define lcd_h
#include "head.h" //本工程公共头文件
#include <hidef.h> //系统头文件,包含开关中断
#include <MC68HC908GP32.h> //芯片头文件
#ifndef lcd_c
//*********全局变量,公共函数定义*************
void Init_HD44780(INT8U setting);
void print1L(INT8U *s);
void print2L(INT8U *s);
//自己模块内的全局变量,公共函数声明给其他模块
#else
//*********本模块自定义函数说明***
void DelaySub(INT16U i,INT16U vector);
void AsmDelay(INT8U delaytime);
void LCD_Command(INT8U cmd);
//自己的私有函数和公共函数声明给自己模块
#endif
#endif
interrupt.c
#define interrupt_c
#include "main.h" //其它模块头文件
#include "lcd.h" //其它模块头文件
#include "interrupt.h" //本模块头文件
//=================全局变量定义=====================================
unsigned char INBUF[8]; //存放PC机发来的8个数据变量
//===================================================================
//===================================================================
//= 函数原型: void SCISend(unsigned char out)
//= 功 能: 用SCI发送一个字节
//= 参 数: 要发送的字节
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void SCISend(unsigned char out)
{
while((SCS1 & 0x80) == 0); //判断SCS1的第7位是否为1,
//是表示发送缓冲空,可以发送
SCDR=out;
}
//===================================================================
//= 函数原型: void MainSend( )
//= 功 能: 接收中断处理函数处理子程序
//= 参 数: 无
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
void MainSend( )
{
int i,m;
unsigned char hand;
for(;;)
{
//等待接收1个字节的信号,收不到数据退出
m=0;
//SCS1第5位为1表示接收缓冲区中有数据可接收
for(i=0;i<0xfff&&((SCS1 & 0x20) == 0);i++);
//i=0xfff表示超时未收到数据
if(i==0xfff) continue;
hand=SCDR; //接收握手信号86
if(hand==0x56) //收到数据,与86比较:
//是,表示计数开始
{
T1SC&=0xdf; //允许定时器1计数寄存器计数
//取PC机发来的6个数据暂存INBUF缓冲区
while (m<=0x07)
{ //SCS1第5位为1表示接收缓冲区中有数据可接收
for(i=0;i<0xfff&&((SCS1 & 0x20) == 0);i++);
//i=0xfff表示超时未收到数据
if(i==0xfff)continue;
INBUF[m]=SCDR; //读取数据
m=m+1;
};
//[显示PC方发来的时钟设置值]
//[1.将发来的6个数据转化为字符]
for(i=0;i<=7;i++)
{
time[i]=INBUF[i];
}
//[2.显示时钟初始值]
print1L((unsigned char*)time);
}
else if(hand==0x57) //不是86,在与87比较:
//是,表示计数结束
{
T1SC|=0x20; //不允许定时器1计数寄存器计数
//[发送当前时钟的时间给PC]
//1.将SerialBuff中的6个数据由字符转化
//为数值型,并发送给PC
for(i=0;i<=7;i++)
{
SCISend(time[i]);
}
//2.将发送缓冲区时钟数据发送出去
}
break;
}
}
//===================================================================
//= 函数原型: interrupt 13 void isrRec(void)
//= 功 能: 接收中断服务函数
//= 参 数: 无
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
interrupt 13 void isrRec(void)
{
asm("SEI"); //禁止所有中断
MainSend( ); //接收8个数据并返发回PC机方显示
asm("CLI"); //开中断
}
//===================================================================
//= 函数原型: interrupt 6 void isrTIMER1(void)
//= 功 能: 定时器1溢出处理程序
//= 参 数: 无
//= 返 回 值: 无
//= 函数性质:私有函数
//===================================================================
interrupt 6 void isrTIMER1(void)
{
asm("SEI");
time[7]=time[7]+1; //秒钟的低位处理
if(time[7]==':')
{
time[7]='0';
time[6]=time[6]+1; //秒钟的高位处理
if(time[6]=='6')
{
time[6]='0';
time[4]=time[4]+1; //分钟的低位处理
if(time[4]==':')
{
time[4]='0';
time[3]=time[3]+1; //分钟的高位处理
if(time[3]=='6')
{
time[3]='0';
time[1]=time[1]+1;//小时的处理
//与小时的24进行比较处理
if(time[1]=='4')
{
if(time[0]=='2')
{
time[1]='0';
time[0]='0';
}
}
else if(time[1]==':')
{
time[1]='0';
time[0]=time[0]+1;
}
}
}
}
}
T1SC&=127; //清除定时器溢出标志位
print1L((unsigned char*)time); //显示时间
asm("CLI");
}
interrupt.h
#ifndef interrupt_h //防止在同一模块多次包含
#define interrupt_h
#include "head.h" //本工程公共头文件
#include <hidef.h> //系统头文件,包含开关中断
#include <MC68HC908GP32.h> //芯片头文件
#ifndef interrupt_c
//*********全局变量,公共函数定义*************
extern unsigned char INBUF[8]; //存放PC机发来的8个数据变量
//自己模块内的全局变量,公共函数声明给其他模块
#else
//*********本模块自定义函数说明***
void SCISend(unsigned char out);
void MainSend();
interrupt 13 void isrRec(void);
interrupt 6 void isrTIMER1(void);
//自己的私有函数和公共函数声明给自己模块
#endif
#endif
head.h
#ifndef _TYPE
#define _TYPE
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef char INT8S;
typedef unsigned int INT16U;
typedef int INT16S;
typedef unsigned long INT32U;
typedef long INT32S;
#endif