嵌入式学习--江协51单片机day5
江协每个模块的学习都是第一集讲原理,第二集将简单应用。如果比较着急的,可以不看第一集,只要明白怎么用就行。
今天学习DS1302时钟和蜂鸣器
DS1302
内部原理图,DS1302是有内部电源,电源的引脚名要注意
这两个原理图比较重要,第一个是寄存器(BIT7-BIT4的单位是10xx,second,minute等是BCD码的存储,在使用时要进行转换),第二个是写和读的过程,模拟这个过程就能对DS1302进行读和写(要注意读的时钟只有15个周期,在模拟的时候要通过重复赋值过滤一个)
DS1302时钟
#include <REGX52.H>//引脚定义
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//时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={19,11,16,12,59,55,6};/*** @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<<i);DS1302_SCLK=1;DS1302_SCLK=0;}for(i=0;i<8;i++){DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}DS1302_CE=0;
}/*** @brief DS1302读一个字节* @param Command 命令字/地址* @retval 读出的数据*/
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<<i);DS1302_SCLK=0;DS1302_SCLK=1;}for(i=0;i<8;i++){DS1302_SCLK=1;DS1302_SCLK=0;if(DS1302_IO){Data|=(0x01<<i);}}DS1302_CE=0;DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错return Data;
}/*** @brief DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中* @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 DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中* @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;
}
DS1302可调时钟
这个主要是比较复杂
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Delay.h"
#include "Timer0.h"
#include "Key.h"
unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
void TimeShow()
{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(2,1,DS1302_Time[3],2);LCD_ShowNum(2,4,DS1302_Time[4],2);LCD_ShowNum(2,7,DS1302_Time[5],2);
}void TimeSet()
{if(KeyNum==2){TimeSetSelect++;TimeSetSelect%=6;}if(KeyNum==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[1]%4==0){if(DS1302_Time[2]>29){DS1302_Time[2]=1;}}else{if(DS1302_Time[1]>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(KeyNum==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[1]%4==0){if(DS1302_Time[2]<1){DS1302_Time[2]=29;}if(DS1302_Time[2]>29){DS1302_Time[2]=1;}}else{if(DS1302_Time[1]<1){DS1302_Time[2]=28;}if(DS1302_Time[1]>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(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);}
}void main()
{LCD_Init();DS1302_Init();LCD_ShowString(1,1," - - ");LCD_ShowString(2,1," : : ");//初始化并设置格式Timer0Init();DS1302_SetTime();while(1){KeyNum=Key();if(KeyNum==1)//按键一按下切换模式{if(MODE==0){MODE=1;}//1是设置0是展示else if(MODE==1){MODE=0;DS1302_SetTime();}}switch(MODE){case 0:TimeShow();break;case 1:TimeSet();break;}}}
void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count>=500){T0Count=0;TimeSetFlashFlag=!TimeSetFlashFlag;}
}
蜂鸣器
这个不用了解地很清楚
蜂鸣器播放提示音
#include <REGX52.H>
#include "Delay.h"
#include <INTRINS.H>
//蜂鸣器端口
sbit Buzzer=P2^5;
/*** @brief 蜂鸣器私有延时函数* @param * @retval */
void Buzzer_Delay500us() //@12.000MHz
{unsigned char i;_nop_();i = 247;while (--i);
}
/*** @brief 蜂鸣器发生* @param ms 发生时长* @retval */
void Buzzer_Time(unsigned int ms)
{unsigned int i;for(i=0;i<ms*2;i++){Buzzer=!Buzzer;Buzzer_Delay500us();}
}
蜂鸣器播放音乐
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"
sbit Buzzer=P2^5;
#define SPEED 250
//音符与索引对应表,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号#
#define P 0
#define L1 1
#define L1_ 2
#define L2 3
#define L2_ 4
#define L3 5
#define L4 6
#define L4_ 7
#define L5 8
#define L5_ 9
#define L6 10
#define L6_ 11
#define L7 12
#define M1 13
#define M1_ 14
#define M2 15
#define M2_ 16
#define M3 17
#define M4 18
#define M4_ 19
#define M5 20
#define M5_ 21
#define M6 22
#define M6_ 23
#define M7 24
#define H1 25
#define H1_ 26
#define H2 27
#define H2_ 28
#define H3 29
#define H4 30
#define H4_ 31
#define H5 32
#define H5_ 33
#define H6 34
#define H6_ 35
#define H7 36unsigned int FreqTable[]={0,63628,
63731,63836,63929,64021,64104,64185,64261,64332,64400,64464,64524,
64580,64634,64685,64733,64778,64820,64861,64899,64935,
64968,65000,65030,65058,65086,65111,65135,65157,65179,65199,65218,65235,65252,65268,65283
};
unsigned char code Music[]={//音符,时值,//1P, 4,P, 4,P, 4,M6, 2,M7, 2,H1, 4+2,M7, 2,H1, 4,H3, 4,M7, 4+4+4,M3, 2,M3, 2,//2M6, 4+2,M5, 2,M6, 4,H1, 4,M5, 4+4+4,M3, 4,M4, 4+2,M3, 2,M4, 4,H1, 4,//3M3, 4+4,P, 2,H1, 2,H1, 2,H1, 2,M7, 4+2,M4_,2,M4_,4,M7, 4,M7, 8,P, 4,M6, 2,M7, 2,//4H1, 4+2,M7, 2,H1, 4,H3, 4,M7, 4+4+4,M3, 2,M3, 2,M6, 4+2,M5, 2,M6, 4,H1, 4,//5M5, 4+4+4,M2, 2,M3, 2,M4, 4,H1, 2,M7, 2+2,H1, 2+4,H2, 2,H2, 2,H3, 2,H1, 2+4+4,//6H1, 2,M7, 2,M6, 2,M6, 2,M7, 4,M5_,4,M6, 4+4+4,H1, 2,H2, 2,H3, 4+2,H2, 2,H3, 4,H5, 4,//7H2, 4+4+4,M5, 2,M5, 2,H1, 4+2,M7, 2,H1, 4,H3, 4,H3, 4+4+4+4,//8M6, 2,M7, 2,H1, 4,M7, 4,H2, 2,H2, 2,H1, 4+2,M5, 2+4+4,H4, 4,H3, 4,H3, 4,H1, 4,//9H3, 4+4+4,H3, 4,H6, 4+4,H5, 4,H5, 4,H3, 2,H2, 2,H1, 4+4,P, 2,H1, 2,//10H2, 4,H1, 2,H2, 2,H2, 4,H5, 4,H3, 4+4+4,H3, 4,H6, 4+4,H5, 4+4,//11H3, 2,H2, 2,H1, 4+4,P, 2,H1, 2,H2, 4,H1, 2,H2, 2+4,M7, 4,M6, 4+4+4,P, 4,0xFF //终止标志
};unsigned char FreqSelect,MusicSelect;void main()
{Timer0Init();while(1){if(Music[MusicSelect]){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
{if(FreqTable[FreqSelect]){TL0 = FreqTable[FreqSelect]%256; //设置定时初值TH0 = FreqTable[FreqSelect]/256; //设置定时初值}Buzzer=!Buzzer;
}