1、 //****************************************************************************// // STC12C5A60S2可编程时钟模块 // // // 说明:STC12C5A60S2单片机有三路可编程时钟输出CLKOUT0/T0/P3.4 // CLKOUT1/T1/P3.5、CLKOUT2/P1.0 // // 涉及寄存器:AUXR(辅助寄存器)、WAKE_CLKO(时钟
2、与系统掉电唤醒控制寄存器)
// BRT(独立波特率发生器定时器寄存器)
//
// 程序说明:
// 本程序可选实现P3.4输出CLKOUT0时钟、P3.5输出CLKOUT1时钟
// P1.0输出CLKOUT2时钟
//
////****************************************************************************//
#include 3、rins.h>
//#define Port_BRT //如果想测试独立波特率发生器时钟输出请打开此句
//若想测试CLKOUT1和CLKOUT0请注释此句
#ifdef Port_BRT /*条件编译独立波特率发生器时钟输出*/
//*********************************//
// CLKOUT2时钟初始化 //
//*********************************//
void CLKOUT_init(void)
{ 4、
WAKE_CLKO = 0x04; //Bit2-BRTCLKO 允许P1.0配置为独立波特率发生器的时钟输出
//BRT工作在1T模式下时的输出频率 = Sysclk/(256-BRT)/2
//BRT工作在12T模式下时输出频率 = Sysclk/12/(256-BRT)/2
AUXR = 0x14; //Bit4-BRTR 允许独立波特率发生器运行
//Bit2-BRTx12 BRT工作在1T模式下
5、
BRT = 0xff; //更改该寄存器的值可实现对输出的时钟频率进行分频
}
#else /*条件编译CLKOUT0时钟输出*/
//*********************************//
// CLKOUT0时钟和CLKOUT1初始化 //
//*********************************//
void CLKOUT_init(void)
{
WAKE_CLKO = 0x03; //允许将P3.4/T0脚配置为定时器0的时钟输出CLKOUT0
6、
//T0工作在1T模式时的输出频率 = SYSclk/(256-TH0)/2
//T0工作在12T模式时的输出频率 = SYSclk/12/(256-TH0)/2
//1T指的是每1个时钟加1,是普通C51的12倍
//12T指的是每12个时钟加1与普通C51一样
//允许将P3.5/T1脚配置 7、为定时器1的时钟输出CLKOUT1,只能工作在定时器模式2下
//T1工作在1T模式时的输出频率 = SYSclk/(256-TH0)/2
//T1工作在12T模式时的输出频率 = SYSclk/12/(256-TH0)/2
//1T指的是每1个时钟加1,是普通C51的12倍
//12T指的是每12个时钟加1与普通C51一样
AUXR = 0xc0; //T 8、0定时器速度是普通8051的12倍,即工作在1T模式下
//T1定时器速度是普通8051的12倍,即工作在1T模式下
TMOD = 0x22; //定时器0工作模式为方式2,自动装载时间常数
//定时器1工作模式为方式2,自动装载时间常数
TH0 = 0xff; //更改该寄存器的值可实现对输出的时钟频率进行分频
TL0 = 0xff;
TH1 = 0xff; //更改该寄存器的值可实现对 9、输出的时钟频率进行分频
TL1 = 0xff;
TR1 = 1;
TR0 = 1;
}
#endif
//**********************************//
// 主程序 //
//**********************************//
void main()
{
CLKOUT_init();
while(1);
}
//************************************** 10、//
// STC12C5A60S2系统时钟模块 //
//
// 说明: STC12C5A60S2单片机有两个时钟源,内部R/C振荡时钟和外部晶体时钟
// 出厂标准配置是使用外部晶体或时钟
//
//
// 涉及寄存器:CLK_DIV(时钟分频寄存器)
// 由该寄存器的Bit0-2组合可实现对时钟源 11、进行0、2、4、8、16
// 32、64、128分频
// //
// 程序说明:
// 对外部时钟进行分频得到Sysclk,然后经过P1.0的独立波特率
// 时钟输出功能Sysclk/2输出时钟频率
//****************************************************************************//
#include 12、s.h>
#define Bus_clk 12 //若要修改系统时钟直接在此处修改
//12 为 12M 的sysclk
//6 为 6M 的sysclk
//3 为 3M 的sysclk
//1500 为 1.5M 的sysclk
//750 为 750kHz 的sysclk
//375 为 375kHz 的sysclk
//187500 13、 为 187.5kHz 的sysclk
//93750 为 93.75kHz 的sysclk
//*********************************************//
// 系统时钟初始化 //
//*********************************************//
void Sysclk_init(void)
{
WAKE_CLKO = 0x04; //配置P1.0口为频率输出
AUXR = 0x14; // 14、允许波特率时钟工作
//工作模式为1T
BRT = 0xff;
#if( Bus_clk == 12 )
CLK_DIV = 0x00;
#elif( Bus_clk == 6 )
CLK_DIV = 0x01;
#elif( Bus_clk == 3 )
CLK_DIV = 0x02;
#elif( Bus_clk == 1500 )
CLK_DIV = 0x03;
#elif( Bus_clk == 750 )
CLK_DIV = 0x0 15、4;
#elif( Bus_clk == 375 )
CLK_DIV = 0x05;
#elif( Bus_clk == 187500 )
CLK_DIV = 0x06;
#elif( Bus_clk == 93750 )
CLK_DIV = 0x07;
#endif
}
//**********************************************//
// 主程序 //
//**********************************************//
16、
void main()
{
Sysclk_init();
while(1);
}
//****************************************************************************//
// STC12C5A60S2系统省电模块 //
//
// 说明: STC12C5A60S2单片机有三种省电模式以降低功耗.空闲模式,低速模式
// 掉电模式
// 17、
//
// 涉及寄存器:PCON(电源控制寄存器)
// Bit0 - IDL 控制单片机进入IDLE空闲模式
// Bit1 - PD 控制单片机进入掉电模式
// //
// 程序说明: 程序实现让单片机先工作一阵子(通过P0^3指示灯显示)
// 然后进入掉电状态,利用外部中断0口来唤醒单片机工作
// 唤醒后单片机将通过P0^0-3口的灯闪烁显示开始工作
////* 18、//
#include 19、
sbit Power_Down_LED_INT0 = P0^1; //INT0口掉电唤醒指示灯
sbit N_Power_Down_LED_INT0 = P0^2; //INT0口没有唤醒指示灯
sbit Normal_Work_LED = P0^3; //正常工作指示灯
sbit Power_Down_Wakeup_INT0= P3^2; //外中断唤醒输入口
void Delay_ms( uint time );
void Normal_work(void);
void Intp 20、init(void);
void After_Powr_Down(void);
//***********************************//
// 软件延时 //
//***********************************//
void Delay_ms( uint time )
{
uint t; //延时时间 = (time*1003+16)us
while(time--)
{
for( t = 0; t < 82; t++ );
21、 }
}
//***********************************//
// 正常工作指示
//***********************************//
void Normal_work(void)
{
Normal_Work_LED = 1;
Delay_ms(500);
Normal_Work_LED = 0;
Delay_ms(500);
}
void After_Power_Down(void)
{
uchar i ;
for( i = 0; i < 22、100; i++ )
{
P0 = 0x0f;
Delay_ms(500);
P0 = 0x00;
Delay_ms(500);
}
}
//***********************************//
// 中断初始化 //
//***********************************//
void Intp_init(void)
{
IT0 = 0; //外部中断源0为低电平触发
EX0 = 1; / 23、/允许外部中断
EA = 1; //开总中断
}
//***********************************//
// 主程序 //
//***********************************//
void main()
{
uchar j = 0;
uchar wakeup_counter = 0; //记录掉电次数
P0 = 0x00;
Chip_Start_LED = 1; //单片机开始工作
Intp_init(); 24、 //外中断0初始化
while(1)
{
P2 = wakeup_counter;
wakeup_counter++;
for( j = 0; j < 250; j++ )
{
Normal_work(); //系统正常工作指示
}
Power_Down_Flag = 1; //系统开始进入掉电状态
PCON = 0x02;
_nop_();
_nop_();
_nop_();
25、
_nop_();
After_Power_Down(); //掉电唤醒后
}
}
//**********************************//
// 中断服务
//**********************************//
void INT0_Service(void) interrupt 0
{
if( Power_Down_Flag ) //掉电唤醒状态指示
{
Power_Down_Flag = 0 26、
Power_Down_LED_INT0 = 1;
while( Power_Down_Wakeup_INT0 == 0 )
{
_nop_(); //等待高电平
}
Power_Down_LED_INT0 = 0;
}
else //未掉电状态
{
N_Power_Down_LED_INT0 = 1; //不是掉电唤醒指示
wh 27、ile( Power_Down_Wakeup_INT0 == 0 )
{
_nop_();
}
N_Power_Down_LED_INT0 = 0;
}
}
//****************************************************************************//
// STC12C5A60S2 A/D转换模块 //
//
// 28、 说明: STC12C5A60S2单片机有8路10位高速AD转换器,P1^0-P1^7
//
// 涉及寄存器:P1ASF(模拟功能控制寄存器)、ADC_CONTR(ADC控制寄存器)
// ADC_RES、ADC_RESL(转换结果寄存器)
//
// 注意: 1、初次打开内部A/D模拟电源需适当延时等内部模拟电源稳定后,再启动A/D转换
// 启动A/D后,在转换结束前不改变任何I/O口的状态,有利于高精度A/D转换
29、// 若能将定时器/串行/中断系统关闭更好。
// 2、A/D转换模块使用的时钟为内部R/C振荡器所产生的系统时钟
// 3、由于使用两套时钟,设置好ADC_CONTR后要加4个空延时操作才可以正确
// 读到ADC_CONTR寄存器的值
////
// 程序说明:
// 本程序实现P1^0口作为A/D采集输入口,对外部电压的测量并将测量结果通过
// 12864和 30、串口显示出来
////****************************************************************************//
#include 31、e Speed_1 0x20 //360 clk
#define Speed_2 0x40 //180 clk
#define Speed_3 0x60 //90 clk
#define ADC0 0x00 //P1.0
#define ADC1 0x01 //P1.1
#define ADC2 0x02 //P1.2
#define ADC3 0x03 //P1.3
#define ADC4 0x04 //P1.4
#define ADC5 0x05 //P1.5
#define ADC6 32、0x06 //P1.6
#define ADC7 0x07 //P1.7
void AD_init(void);
double Result_Calculate(void);
void SendData( uchar byte );
//**********************************//
// A/D初始化 //
//**********************************//
void AD_init(void)
{
AUXR1 = 0x04; 33、 //转换结果高2位放在ADC_RES的低2位中,低8位放在ADC_RESL中
P1ASF = 0x01; //P1.0口作为模拟功能A/D使用
ADC_RES = 0x00; //结果清零
ADC_RESL = 0x00;
ADC_CONTR = ADC_POWER|Speed_2|ADC0|ADC_START; //打开电源,180CLK周期转换,选择P1.0作输入
_nop_();
_nop_();
_nop_();
34、 _nop_();
_nop_();
_nop_();
_nop_();
_nop_();
EADC = 1; //允许A/D转换中断
EA = 1; //开总中断
}
//****************************************//
// 串口初始化 //
//*************** 35、//
void UART_init(void)
{
SM0 = 0; //选择串口为方式1工作
SM1 = 1; //8位数据波特率可变
REN = 1;
BRT = 0xDC;
AUXR = 0x15; //选择独立波特率发生器为串行
//口的波特率发生器,模式为1T
}
//******************************************//
// 转换结果计算 36、//
//******************************************//
double Result_Calculate(void)
{
uint temp;
double result;
temp = ADC_RES * 256 + ADC_RESL;
result = temp * 4.94 / 1024;
return result;
}
//******************************************//
// 串口发送数据 / 37、/
//******************************************//
void SendData( uchar byte )
{
SBUF = byte;
while(!TI);
TI = 0;
}
//******************************************//
// 主程序 //
//******************************************//
void main()
{
Init_LCD() 38、
AD_init();
UART_init();
while(1);
}
//******************************************//
// A/D中断服务 //
//******************************************//
void AD_Service(void) interrupt 5
{
ADC_CONTR &= !ADC_FLAG; //清标志
Printf_Decimal(Result_Calculate()) 39、
ADC_RES = 0x00;
ADC_RESL = 0x00;
ADC_CONTR = ADC_POWER|Speed_2|ADC_START; //开始下一次转换
_nop_();
_nop_();
_nop_();
_nop_();
}
#include 40、选择 1-并行 0-串行
sbit RS = P0^7; //并行数据/命令选择,串行片选 0-指令 1-数据
sbit RW = P0^6; //并行读写选择 0-写 1-读 串行数据口
sbit E = P0^5; //并行使能, 串行同步时钟
void Delay_ms( uint time ); //延时
uchar Busy(void); //读忙
uchar Read_Status(void);//读状态
uchar Read_Date(void); //读数据
void Write_Cmd( uchar cmd ); //写命令
voi 41、d Write_Date( uchar date );//写数据
void Init_LCD(void);//初始化LCD
void Location( uchar x, uchar y );//设定显示位置
void Clear_Screen(void);//清屏
void Write_str( uchar *p );
void Printf_Decimal(double Num);
#include "lcd.h"
extern void SendData( uchar byte );
/***********以下部分为LCD的驱动 42、程序*************/
//**********************************//
//* 名称: Delay_ms()
//* 功能: 实现软件延时
//* 输入: time - 时间参数
//* 输出: 无
//**********************************//
void Delay_ms( uint time )
{
uint t; //82,延时时间 = (time*1003+16)us
while(time--) //41,延时时间 = (time*499 43、16)us
{
for( t = 0; t < 41; t++ );
}
}
//**********************************//
//* 名称: Busy()
//* 功能: 读取忙状态
//* 输入: 无
//* 输出: 1-忙 0-空闲
//**********************************//
uchar Busy(void)
{
uchar busy,flag;
Delay_ms(1);
busy = Read_Status();
if( bus 44、y & 0x80 )
flag = 1;
else
flag = 0;
Delay_ms(1);
return flag;
}
//**********************************//
//* 名称: Read_Status()
//* 功能: 读12864状态
//* 输入: 无
//* 输出: status-当前状态
//**********************************//
uchar Read_Status(void)
{
uchar status;
45、 RS = 0;
RW = 1;
E = 0;
_nop_();
_nop_();
_nop_();
E = 1;
Delay_ms(1);
status = P2;
Delay_ms(1);
E = 0;
_nop_();
_nop_();
return status;
}
//**********************************//
//* 名称: Write_Cmd()
//* 功能: 向12864写命令
//* 输入: cmd 46、 命令参数
//* 输出: 无
//**********************************//
void Write_Cmd( uchar cmd )
{
RS = 0;
RW = 0;
E = 0;
Delay_ms(1);
P2 = cmd;
Delay_ms(1);//等待数据稳定
E = 1;
Delay_ms(1);
E = 0;
}
//********************** 47、//
//* 名称: Write_Date()
//* 功能: 向12864写数据
//* 输入: date - 待写入的数据
//* 输出: 无
//**********************************//
void Write_Date( uchar date )
{
while(Busy());
RS = 1;
RW = 0;
E = 0;
_nop_();
_nop_();
P2 = date;
Delay_ms(1);//待数据稳定
E = 48、1;
Delay_ms(1);
E = 0;
_nop_();
_nop_();
}
//**********************************//
//* 名称: Read_Date()
//* 功能: 向12864读数据
//* 输入: 无
//* 输出: date - 返回的数据
//**********************************//
uchar Read_Date(void)
{
uchar date;
while(Busy()); //忙
RS = 1;
49、 RW = 1;
E = 0;
_nop_();
_nop_();
_nop_();
E = 1;
Delay_ms(1);
date = P2;
Delay_ms(1);
E = 0;
_nop_();
return date;
}
//**********************************//
//* 名称: Init_LCD()
//* 功能: 初始化LCD
//* 输入: 无
//* 输出: 无
//************************ 50、//
void Init_LCD(void)
{
Delay_ms(4);
PSB = 1;//并行方式
Delay_ms(4);
Write_Cmd(0x0c);//开显示关游标
Delay_ms(4);
Clear_Screen();//清屏
}
//**********************************//
//* 名称: Location()
//* 功能: 设定显示位置
//* 输入: x,y --X轴点 --Y轴点
//* x 只能是1-4中的一个数
/






