目录
七、矩阵键盘
八、定时器和中断
九、串口通信
十、LED点阵屏
十一、DS1302实时时钟
十二、蜂鸣器
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
#include
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的瞬间,返回键码,没有按键按下时,返回零。
*/
unsigned char MatrixKey(){
unsigned char KeyNumber=0;
// 按列扫描
// 第一列
P1=0xFF;
P1_3=0;
if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
// 第二列
P1=0xFF;
P1_2=0;
if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
// 第三列
P1=0xFF;
P1_1=0;
if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
// 第四列
P1=0xFF;
P1_0=0;
if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
#include
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main(){
LCD_Init();
LCD_ShowString(1,1,"Which One?");
while(1){
KeyNum=MatrixKey();
if(KeyNum){ // 不加if,KeyNum会马上刷新为0
LCD_ShowNum(2,1,KeyNum,2);
}
}
}
#include
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Password,Count;
void main(){
LCD_Init();
LCD_ShowString(1,1,"Password:");
while(1){
KeyNum=MatrixKey();
if(KeyNum){ // 不加if,KeyNum会马上刷新为0
if(KeyNum<=10){ // 如果是s1~s10按下,输入密码
if(Count<4){ // 限制密码位数
Password*=10; // 密码左移一位
Password+=KeyNum%10; // 将10转化为0,获得一位密码
Count++; // 记录密码位数
}
}
LCD_ShowNum(2,1,Password,4); // 更新显示
}
if(KeyNum==11){ // s11按下,确认
if(Password==1234){ // 判断密码
LCD_ShowString(1,11,"TRUE"); // 密码正确
Password=0; // 密码清零
Count=0; // 计次清零
LCD_ShowNum(2,1,Password,4); // 更新显示
}else{
LCD_ShowString(1,11,"ERR"); // 密码错误
Password=0; // 密码清零
Count=0; // 计次清零
LCD_ShowNum(2,1,Password,4); // 更新显示
}
}
if(KeyNum==12){ // s12按下,取消
Password=0; // 密码清零
Count=0; // 计次清零
LCD_ShowNum(2,1,Password,4); // 更新显示
}
}
}
//定时器0初始化
void Timer0Init(){
//TMOD=0x01; // 0000 0001 这样赋值在同时使用定时器1和定时器0时可能会产生冲突
TMOD&=0xF0; // 把TMOD低四位清零,高四位不变
TMOD|=TMOD|0x01; // 把TMOD最低位置1,高四位不变
TF0=0; // 中断溢出标志位
TR0=1; // 开启定时器
// 初始化计数器
TH0=64535/256; // 取高位
TL0=64535%256+1; // 取低位
// 配置中断
ET0=1; // 允许中断
EA=1; // 允许总中断
PT0=0; // 中断优先级
}
void Timer0Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
// 配置中断
ET0=1; // 允许中断
EA=1; // 允许总中断
PT0=0; // 中断优先级
}
#include
/**
* @brief 定时器0初始化,1毫秒@12.000MHz
* @param 无
* @retval 无
*/
void Timer0Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
// 配置中断
ET0=1;
EA=1;
PT0=0;
}
/* 定时器中断函数模板
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000){
T0Count=0;
P2_0=~P2_0;
}
}
*/
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0Init(void);
#endif
#include
#include "Delay.h"
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时,返回0
*/
unsigned char Key(){
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
#include
#include "Timer0.h"
#include "Key.h"
#include // 引入_crol_()和_cror_()循环移位函数
unsigned char KeyNum,LEDMode;
void main(){
Timer0Init(); // 定时器0初始化
P2=0xFE; // 初始化LED
while(1){ // 每当定时器溢出,就跳转执行中断函数
KeyNum=Key();
if(KeyNum){
if(KeyNum==1){
LEDMode++;
if(LEDMode>=2) LEDMode=0; // LEDMode只在0和1变化
}
}
}
}
// 中断函数
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=500){ // 每隔0.5ms让LED移动
T0Count=0;
if(LEDMode==0)
P2=_crol_(P2,1); // P2左移1位
else P2=_cror_(P2,1); // P2右移1位
}
}
#include
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
unsigned char Sec=55,Min=59,Hour=23;
void main(){
LCD_Init();
Timer0Init();
LCD_ShowString(1,1,"Clock:");
LCD_ShowString(2,1," : :");
while(1){
LCD_ShowNum(2,1,Hour,2); // 小时
LCD_ShowNum(2,4,Min,2); // 分钟
LCD_ShowNum(2,7,Sec,2); // 秒
}
}
// 中断函数
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000){
T0Count=0;
Sec++;
if(Sec>=60){
Sec=0;
Min++;
if(Min>=60){
Min=0;
Hour++;
if(Hour>=24) Hour=0;
}
}
}
}
// 串口初始化
void UART_Init(){ // [email protected]
PCON |= 0x80;
SCON = 0x40;
// 配置定时器1(只允许使用定时器1)
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设置定时初值
TH1 = 0xF3; //设置定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
#include
/**
* @brief 串口初始化,[email protected]
* @param 无
* @retval 无
*/
void UART_Init(){
PCON |= 0x80;
SCON = 0x50;
// 配置定时器1(只允许使用定时器1)
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设置定时初值
TH1 = 0xF3; //设置定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte){
SBUF=Byte; // 串口缓冲寄存器
while(TI==0); // 检测是否完成。机械控制为1,即TI为1时发送完成。
TI=0; // 软件复位
}
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif
#include
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main(){
UART_Init();
while(1){
UART_SendByte(Sec);
Sec++;
Delay(1000);
}
}
void UART_Init(){
PCON |= 0x80;
SCON = 0x50;
// 配置定时器1(只允许使用定时器1)
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设置定时初值
TH1 = 0xF3; //设置定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
// 配置中断
EA=1; // 启动所有中断
ES=1;// 启动串口中断
}
#include
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main(){
UART_Init();
while(1){
}
}
void UART_Rountine() interrupt 4{ // 当单片机串口接收到数据时,该中断函数会执行
if(RI==1){ // 接收中断请求标志位,将发送和接收区分开
P2=~SBUF;
UART_SendByte(SBUF); // 将单片机收到的数据发送到电脑显示
RI=0; // 软件复位
}
}
#include
#include "Delay.h"
sbit RCK=P3^5; // RCLK寄存器时钟
sbit SCK=P3^6; // SRCLK串行时钟
sbit SER=P3^4; // SER串行数据
#define MATRIX_LED_PORT P0
void MatrixLED_Init(){ // 初始化74HC595
SCK=0;
RCK=0;
}
void _74HC595_WriteByte(unsigned char Byte){ // 控制行
unsigned char i;
for(i=0;i<8;i++){ // 将8位数据放入移位寄存器
SER=Byte&(0x80>>i); // 非0赋1
SCK=1; // 移位
SCK=0;
}
RCK=1; // 将8位数据输出
RCK=0;
}
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Line){
_74HC595_WriteByte(Line); // 第几行亮
MATRIX_LED_PORT=~(0x80>>Column); // 第几列亮,0选中
Delay(1); // 消影
MATRIX_LED_PORT=0xFF;
}
void main(){
MatrixLED_Init();
while(1){
MatrixLED_ShowColumn(0,0x3C);
MatrixLED_ShowColumn(1,0x42);
MatrixLED_ShowColumn(2,0xA9);
MatrixLED_ShowColumn(3,0x85);
MatrixLED_ShowColumn(4,0x85);
MatrixLED_ShowColumn(5,0xA9);
MatrixLED_ShowColumn(6,0x42);
MatrixLED_ShowColumn(7,0x3C);
}
}
#include
#include "Delay.h"
sbit RCK=P3^5; // RCLK寄存器时钟
sbit SCK=P3^6; // SRCLK串行时钟
sbit SER=P3^4; // SER串行数据
#define MATRIX_LED_PORT P0
/**
* @brief LED点阵屏初始化
* @param 无
* @retval 无
*/
void MatrixLED_Init(){ // 初始化74HC595
SCK=0;
RCK=0;
}
/**
* @brief 74HC595写入一个字节
* @param 要写入的字节
* @retval 无
*/
void _74HC595_WriteByte(unsigned char Byte){ // 控制行
unsigned char i;
for(i=0;i<8;i++){ // 将8位数据放入移位寄存器
SER=Byte&(0x80>>i); // 非0赋1
SCK=1; // 移位
SCK=0;
}
RCK=1; // 将8位数据输出
RCK=0;
}
/**
* @brief LED点阵屏显示一列数据
* @param Column 要选择的列,范围:0~7,0在最左边
* @param Line 选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Line){
_74HC595_WriteByte(Line); // 第几行亮
MATRIX_LED_PORT=~(0x80>>Column); // 第几列亮,0选中
Delay(1); // 消影
MATRIX_LED_PORT=0xFF;
}
#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__
void MatrixLED_Init();
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Line);
#endif
#include
#include "Delay.h"
#include "MatrixLED.h"
unsigned char code Animation[]={ // code将数组放入flash中
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 为了让动画流畅,开头让动画流水出现
0xFF,0x08,0x08,0x08,0xFF,0x00,0x0E,0x15,
0x15,0x0C,0x00,0x7E,0x01,0x01,0x02,0x00,
0x7E,0x01,0x01,0x02,0x00,0x0E,0x11,0x11,
0x0E,0x00,0x7D,0x00,0x7D,0x00,0x7D,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 显示完空的8列,再显示新的,才不会扰乱前面的显示
};
void main(){
unsigned char i,offset,Count;
MatrixLED_Init();
while(1){
for(i=0;i<8;i++){
MatrixLED_ShowColumn(i,Animation[i+offset]);
}
Count++;
if(Count>10){ // 一帧扫描十遍,不能用延时函数,会显得动画不流畅
Count=0;
offset++;
if(offset>40) offset=0;
}
}
}
#include
sbit DS1302_SCLK=P3^6; // 串行时钟
sbit DS1302_IO=P3^4; // 数据输入/输出
sbit DS1302_CE=P3^5; // 芯片使能
// 写入地址
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
char DS1302_TIME[]={23,8,11,13,59,55,5};
/**
* @brief 初始化DS1302时钟
* @param 无
* @retval 无
*/
void DS1302_Init(void){
DS1302_CE=0;
DS1302_SCLK=0;
}
/**
* @brief 向DS1302中写入一个字节数据
* @param Command 要写入的命令
* @param Data 要写入的数据
* @retval 无
*/
void DS1302_WriteByte(unsigned char Command,Data){
unsigned char i;
DS1302_CE=1;
// 输入控制位
for(i=0;i<8;i++){
DS1302_IO=Command&(0x01<1; // 时序,一个上升下降沿读取IO口的一位
DS1302_SCLK=0;
}
// 输入数据
for(i=0;i<8;i++){
DS1302_IO=Data&(0x01<1; // 时序
DS1302_SCLK=0;
}
DS1302_CE=0;
}
/**
* @brief 从DS1302读出一个字节数据
* @param Command 要写入的命令
* @retval Data 读出的一个字节数据
*/
unsigned char DS1302_ReadByte(unsigned char Command){
unsigned char i,Data=0x00;
Command|=0x01; // 将写的地址改为读的地址
DS1302_CE=1;
// 输入控制位
for(i=0;i<8;i++){
DS1302_IO=Command&(0x01<0; // 时序
DS1302_SCLK=1;
}
// 读取数据
for(i=0;i<8;i++){
DS1302_SCLK=1;
DS1302_SCLK=0;
if(DS1302_IO){ Data|=(0x01<// 将对应位置1
}
DS1302_CE=0;
DS1302_IO=0;
return Data;
}
/**
* @brief 使用数组设置时间
* @param 无
* @retval 无
*/
void DS1302_SetTime(void){
DS1302_WriteByte(DS1302_WP,0x00); // 关闭芯片写保护
DS1302_WriteByte(DS1302_YEAR,DS1302_TIME[0]/10*16+DS1302_TIME[0]%10); // 十进制转BCD
DS1302_WriteByte(DS1302_MONTH,DS1302_TIME[1]/10*16+DS1302_TIME[1]%10);
DS1302_WriteByte(DS1302_DATE,DS1302_TIME[2]/10*16+DS1302_TIME[2]%10);
DS1302_WriteByte(DS1302_HOUR,DS1302_TIME[3]/10*16+DS1302_TIME[3]%10);
DS1302_WriteByte(DS1302_MINUTE,DS1302_TIME[4]/10*16+DS1302_TIME[4]%10);
DS1302_WriteByte(DS1302_SECOND,DS1302_TIME[5]/10*16+DS1302_TIME[5]%10);
DS1302_WriteByte(DS1302_DAY,DS1302_TIME[6]/10*16+DS1302_TIME[6]%10);
DS1302_WriteByte(DS1302_WP,0x80); // 打开芯片写保护
}
/**
* @brief 读取时间到数组
* @param 无
* @retval 无
*/
void DS1302_ReadTime(void){
unsigned char Temp;
Temp=DS1302_ReadByte(DS1302_YEAR);
DS1302_TIME[0]=Temp/16*10+Temp%16; // BCD转十进制
Temp=DS1302_ReadByte(DS1302_MONTH);
DS1302_TIME[1]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_DATE);
DS1302_TIME[2]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_HOUR);
DS1302_TIME[3]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_MINUTE);
DS1302_TIME[4]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_SECOND);
DS1302_TIME[5]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_DAY);
DS1302_TIME[6]=Temp/16*10+Temp%16;
}
#ifndef __DS1302_H__
#define __DS1302_H__
void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_ReadTime(void);
void DS1302_SetTime(void);
extern char DS1302_TIME[];
#endif
#include
#include "LCD1602.h"
#include "DS1302.h"
void main(){
LCD_Init();
DS1302_Init();
LCD_ShowString(1,1," / / ( )");
LCD_ShowString(2,1," : :");
DS1302_SetTime();
while(1){
DS1302_ReadTime();
LCD_ShowNum(1,1,DS1302_TIME[0],2);
LCD_ShowNum(1,4,DS1302_TIME[1],2);
LCD_ShowNum(1,7,DS1302_TIME[2],2);
LCD_ShowNum(1,10,DS1302_TIME[6],1); // 星期
LCD_ShowNum(2,1,DS1302_TIME[3],2);
LCD_ShowNum(2,4,DS1302_TIME[4],2);
LCD_ShowNum(2,7,DS1302_TIME[5],2);
}
}
#include
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
/**
* @brief 显示时间
* @param 无
* @retval 无
*/
void TimeShow(void){
DS1302_ReadTime();
LCD_ShowNum(1,1,DS1302_TIME[0],2);
LCD_ShowNum(1,4,DS1302_TIME[1],2);
LCD_ShowNum(1,7,DS1302_TIME[2],2);
LCD_ShowNum(1,10,DS1302_TIME[6],1); // 星期
LCD_ShowNum(2,1,DS1302_TIME[3],2);
LCD_ShowNum(2,4,DS1302_TIME[4],2);
LCD_ShowNum(2,7,DS1302_TIME[5],2);
}
/**
* @brief 调节时间
* @param 无
* @retval 无
*/
void TimeSet(void){
if(KeyNum==2){ // 按键按键2选择要更新的位置
TimeSetSelect++;
TimeSetSelect%=7; // 越界清零
}else if(KeyNum==3){ // 按键按键3数字加一
DS1302_TIME[TimeSetSelect]++;
// 上界判断
if(DS1302_TIME[0]>99) DS1302_TIME[0]=0; // 年
if(DS1302_TIME[1]>12) DS1302_TIME[1]=1; // 月
// 日
if(DS1302_TIME[1]==1 || DS1302_TIME[1]==3 || DS1302_TIME[1]==5 || DS1302_TIME[1]==7 ||
DS1302_TIME[1]==8 || DS1302_TIME[1]==10 || DS1302_TIME[1]==12){
if(DS1302_TIME[2]>31) DS1302_TIME[2]=1;
}else if(DS1302_TIME[1]==4 || DS1302_TIME[1]==6 || DS1302_TIME[1]==9 || DS1302_TIME[1]==11){
if(DS1302_TIME[2]>30) DS1302_TIME[2]=1;
}else if(DS1302_TIME[1]==2){
if(DS1302_TIME[0]%4==0 && DS1302_TIME[0]%100!=0){ // 闰年
if(DS1302_TIME[2]>29) DS1302_TIME[2]=1;
}else{
if(DS1302_TIME[2]>28) DS1302_TIME[2]=1; // 平年
}
}
if(DS1302_TIME[3]>23) DS1302_TIME[3]=0; // 时
if(DS1302_TIME[4]>59) DS1302_TIME[4]=0; // 分
if(DS1302_TIME[5]>59) DS1302_TIME[5]=0; // 秒
if(DS1302_TIME[6]>7) DS1302_TIME[6]=1; // 星期
}else if(KeyNum==4){ // 按键按键4数字减一
DS1302_TIME[TimeSetSelect]--;
// 下界判断
if(DS1302_TIME[0]<0) DS1302_TIME[0]=99; // 年
if(DS1302_TIME[1]<1) DS1302_TIME[1]=12; // 月
// 日
if(DS1302_TIME[1]==1 || DS1302_TIME[1]==3 || DS1302_TIME[1]==5 || DS1302_TIME[1]==7 ||
DS1302_TIME[1]==8 || DS1302_TIME[1]==10 || DS1302_TIME[1]==12){
if(DS1302_TIME[2]<1) DS1302_TIME[2]=31;
if(DS1302_TIME[2]>31) DS1302_TIME[2]=1;
}else if(DS1302_TIME[1]==4 || DS1302_TIME[1]==6 || DS1302_TIME[1]==9 || DS1302_TIME[1]==11){
if(DS1302_TIME[2]<1) DS1302_TIME[2]=30;
if(DS1302_TIME[2]>30) DS1302_TIME[2]=1;
}else if(DS1302_TIME[1]==2){
if(DS1302_TIME[0]%4==0 && DS1302_TIME[0]%100!=0){ // 闰年
if(DS1302_TIME[2]<1) DS1302_TIME[2]=29;
if(DS1302_TIME[2]>29) DS1302_TIME[2]=1;
}else{
if(DS1302_TIME[2]<1) DS1302_TIME[2]=28; // 平年
if(DS1302_TIME[2]>28) DS1302_TIME[2]=1;
}
}
if(DS1302_TIME[3]<0) DS1302_TIME[3]=23; // 时
if(DS1302_TIME[4]<0) DS1302_TIME[4]=59; // 分
if(DS1302_TIME[5]<0) DS1302_TIME[5]=59; // 秒
if(DS1302_TIME[6]<1) DS1302_TIME[6]=7; // 星期
}
// 更新显示
if(TimeSetSelect==0 && TimeSetFlashFlag==1) LCD_ShowString(1,1," ");
else LCD_ShowNum(1,1,DS1302_TIME[0],2);
if(TimeSetSelect==1 && TimeSetFlashFlag==1) LCD_ShowString(1,4," ");
else LCD_ShowNum(1,4,DS1302_TIME[1],2);
if(TimeSetSelect==2 && TimeSetFlashFlag==1) LCD_ShowString(1,7," ");
else LCD_ShowNum(1,7,DS1302_TIME[2],2);
if(TimeSetSelect==3 && TimeSetFlashFlag==1) LCD_ShowString(2,1," ");
else LCD_ShowNum(2,1,DS1302_TIME[3],2);
if(TimeSetSelect==4 && TimeSetFlashFlag==1) LCD_ShowString(2,4," ");
else LCD_ShowNum(2,4,DS1302_TIME[4],2);
if(TimeSetSelect==5 && TimeSetFlashFlag==1) LCD_ShowString(2,7," ");
else LCD_ShowNum(2,7,DS1302_TIME[5],2);
if(TimeSetSelect==6 && TimeSetFlashFlag==1) LCD_ShowString(1,10," ");
else LCD_ShowNum(1,10,DS1302_TIME[6],1);
LCD_ShowNum(2,10,TimeSetSelect,1);
}
void main(){
LCD_Init();
DS1302_Init();
Timer0Init();
LCD_ShowString(1,1," / / ( )");
LCD_ShowString(2,1," : :");
DS1302_SetTime();
while(1){
KeyNum=Key(); // 获取键码值
if(KeyNum==1){ // 按下按键1修改/保存时间
if(MODE==0) {MODE=1;TimeSetSelect=0;}
else if(MODE==1) {MODE=0;DS1302_SetTime();}
}
switch(MODE){
case 0:TimeShow();break;
case 1:TimeSet();break;
}
}
}
// 定时器0
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=500){ // 5ms
T0Count=0;
TimeSetFlashFlag=!TimeSetFlashFlag;
}
}
for(i=0;i<500;i++){
Buzzer=!Buzzer; // 蜂鸣器控制引脚
Delay(1); // 每隔一毫秒翻转一次,周期为2毫秒,频率为500HZ
} // 以500HZ的频率响500ms
#include
#include
// 蜂鸣器端口
sbit Buzzer=P2^5;
/**
* @brief 蜂鸣器私有延时函数,延时500微秒
* @param 无
* @retval 无
*/
void Buzzer_Delay500us() //@12.000MHz
{
unsigned char i;
_nop_(); // 延时一个机器周期
i = 247;
while (--i);
}
/**
* @brief 让蜂鸣器以1000HZ的频率发声
* @param ms 发声时长
* @retval 无
*/
void Buzzer_Time(unsigned int ms){
unsigned int i;
for(i=0;i2;i++){
Buzzer=!Buzzer;
Buzzer_Delay500us(); // 每隔500微秒翻转一次,周期为1毫秒,频率为1000HZ
}
}
#ifndef __BUZZER_H__
#define __BUZZER_H__
void Buzzer_Time(unsigned int ms);
#endif
#include
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Buzzer.h"
unsigned char KeyNum;
void main(){
Nixie_Static(1,0);
while(1){
KeyNum=Key();
if(KeyNum){
Buzzer_Time(100); // 蜂鸣器发声100ms
Nixie_Static(1,KeyNum); // 显示对应按键的键码
}
}
}
#include
#include "Delay.h"
#include "Timer0.h"
sbit Buzzer=P2^5;
#define SPEED 500 //十六分音符时长
unsigned int FreqTable[]={ // 低中高音
0, // 休止符
63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283
};
unsigned char Music[]={
13,4,
13,4,
20,4,
20,4,
22,4,
22,4,
20,8,
0,2,
18,4,
18,4,
17,4,
17,4,
15,4,
15,4,
13,8,
0xFF, // 终止标志
};
unsigned char FreqSelect=0,MusicSelect=0;
void main(){
Timer0Init();
while(1){
if(Music[MusicSelect]!=0xFF){
FreqSelect=Music[MusicSelect];
MusicSelect++;
Delay(SPEED/4*Music[MusicSelect]);
MusicSelect++;
// 不让音符连在一起
TR0=0;
Delay(5);
TR0=1;
}else{
TR0=0;
while(1);
}
}
}
void Timer0_Routine() interrupt 1{ // 1ms执行一次,500HZ
if(FreqTable[FreqSelect]){
TL0 = FreqTable[FreqSelect]%256; //设置定时初值
TH0 = FreqTable[FreqSelect]/256; //设置定时初值
Buzzer=!Buzzer;
}
}