//****************************************************************************//
// STC12C5A60S2可编程时钟模块
//
//
// 说明:STC12C5A60S2单片机有三路可编程时钟输出CLKOUT0/T0/P3.4
// CLKOUT1/T1/P3.5、CLKOUT2/P1.0
//
// 涉及寄存器:AUXR(辅助寄存器)、WAKE_CLKO(时钟与系统掉电唤醒控制寄存
器)
// BRT(独立波特率发生器定时器寄存器)
//
// 程序说明:
// 本程序可选实现P3.4输出CLKOUT0时钟、P3.5输出CLKOUT1时
钟
// P1.0输出CLKOUT2时钟
//
////****************************************************************************/
/
#include
#include
//#define Port_BRT //如果想测试独立波特率发生器时钟输出请打开此句
//若想测试CLKOUT1和CLKOUT0请注释此句
#ifdef Port_BRT /*条件编译独立波特率发生器时钟输出*/
//*********************************//
// CLKOUT2时钟初始化 //
//*********************************//
void CLKOUT_init(void)
{
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模式下
BRT = 0xff; //更改该寄存器的值可实现对输出的时钟频率进行分频
}
#else /*条件编译CLKOUT0时钟输出*/
//*********************************//
// CLKOUT0时钟和CLKOUT1初始化 //
//*********************************//
void CLKOUT_init(void)
{
WAKE_CLKO = 0x03; //允许将P3.4/T0脚配置为定时器0的时钟输出CLKOUT0
//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脚配置为定时器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; //T0定时器速度是普通8051的12倍,即工作在1T模式下
//T1定时器速度是普通8051的12倍,即工作在1T模式下
TMOD = 0x22; //定时器0工作模式为方式2,自动装载时间常数
//定时器1工作模式为方式2,自动装载时间常数
TH0 = 0xff; //更改该寄存器的值可实现对输出的时钟频率进行分频
TL0 = 0xff;
TH1 = 0xff; //更改该寄存器的值可实现对输出的时钟频率进行分频
TL1 = 0xff;
TR1 = 1;
TR0 = 1;
}
#endif
//**********************************//
// 主程序 //
//**********************************
//
void main()
{
CLKOUT_init();
while(1);
}
//****************************************************************************//
// STC12C5A60S2系统时钟模块
//
//
// 说明: STC12C5A60S2单片机有两个时钟源,内部R/C振荡时钟和外部晶体时
钟
// 出厂标准配置是使用外部晶体或时钟
//
//
// 涉及寄存器:CLK_DIV(时钟分频寄存器)
// 由该寄存器的Bit0-2组合可实现对时钟源进行0、2、4、8、16
// 32、64、128分频
// //
// 程序说明:
// 对外部时钟进行分频得到Sysclk,然后经过P1.0的独立波特率
// 时钟输出功能Sysclk/2输出时钟频率
//****************************************************************************//
#include
#include
#define Bus_clk 12 //若要修改系统时钟直接在此处修改
//12 为 12M 的sysclk
//6 为 6M 的sysclk
//3 为 3M 的sysclk
//1500 为 1.5M 的sysclk
//750 为 750kHz 的sysclk
//375 为 375kHz 的sysclk
//187500 为 187.5kHz 的sysclk
//93750 为 93.75kHz 的sysclk
//*********************************************//
// 系统时钟初始化 //
//*********************************************//
void Sysclk_init(void)
{
WAKE_CLKO = 0x04; //配置P1.0口为频率输出
AUXR = 0x14; //允许波特率时钟工作
//工作模式为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 = 0x04;
#elif( Bus_clk == 375 )
CLK_DIV = 0x05;
#elif( Bus_clk == 187500 )
CLK_DIV = 0x06;
#elif( Bus_clk == 93750 )
CLK_DIV = 0x07;
#endif
}
//**********************************************//
// 主程序 //
//**********************************************//
void main()
{
Sysclk_init();
while(1);
}
//****************************************************************************//
// STC12C5A60S2系统省电模块 //
//
// 说明: STC12C5A60S2单片机有三种省电模式以降低功耗.空闲模式,低速模式
// 掉电模式
//
//
// 涉及寄存器:PCON(电源控制寄存器)
// Bit0 - IDL 控制单片机进入IDLE空闲模式
// Bit1 - PD 控制单片机进入掉电模式
// //
// 程序说明: 程序实现让单片机先工作一阵子(通过P0^3指示灯显示)
// 然后进入掉电状态,利用外部中断0口来唤醒单片机工作
// 唤醒后单片机将通过P0^0-3口的灯闪烁显示开始工作
////****************************************************************************/
/
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar Power_Down_Flag = 0; //进入掉电状态标志
sbit Chip_Start_LED = P0^0; //单片机开始工作指示灯
sbi
t 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_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++ );
}
}
//***********************************//
// 正常工作指示
//***********************************//
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 < 100; i++ )
{
P0 = 0x0f;
Delay_ms(500);
P0 = 0x00;
Delay_ms(500);
}
}
//***********************************//
// 中断初始化 //
//***********************************//
void Intp_init(void)
{
IT0 = 0; //外部中断源0为低电平触发
EX0 = 1; //允许外部中断
EA = 1; //开总中断
}
//***********************************//
STC12C5A60S2单片机各个模块程序代码13_stc12c5a60s2
// 主程序 //
//***********************************//
void main()
{
uchar j = 0;
uchar wakeup_counter = 0; //记录掉电次数
P0 = 0x00;
Chip_Start_LED = 1; //单片机开始工作
Intp_init(); //外中断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_();
_nop_();
After_Power_Down(); //掉电唤醒后
}
}
//**********************************//
// 中断服务
//**********************************//
void INT0_Service(void) interrupt 0
{
if( Power_Down_Flag ) //掉电唤醒状态指示
{
Power_Down_Flag = 0;
Power_Down_LED_INT0 = 1;
while( Power_Down_Wakeup_INT0 == 0 )
{
_nop_(); //等待高电平
}
Power_Down_LED_INT0 = 0;
}
else //未掉电状态
{
N_Power_Down_LED_INT0 = 1; //不是掉电唤醒指示
while( Power_Down_Wakeup_INT0 == 0 )
{
_nop_();
}
N_Power_Down_LED_INT0 = 0;
}
}
//****************************************************************************//
// STC12C5A60S2 A/D转换模块 //
//
// 说明: 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转
换
// 若能将定时器/串行/中断系统关闭更好。
// 2、A/D转换模块使用的时钟为内部R/C振荡器所产生的系统时钟
// 3、由于使用两套时钟,设置好ADC_CONTR后要加4个空延时操作才可
以正确
// 读到ADC_CONTR寄存器的值
////
// 程序说明:
// 本程序实现P1^0口作为A/D采集输入口,对外部电压的测量并将测量
结果通过
// 12864和串口显示出来
////****************************************************************************/
/
#include
#include
#include "lcd.h"
#define ADC_POWER 0x80 //AD电源控制
#define ADC_START 0x08 //AD转换控制
#define ADC_FLAG 0x10 //AD转换完成
#define Speed_0 0x00 //540 clk
#define 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 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; //转换结果高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_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
EADC = 1; //允许A/D转换中断
EA = 1; //开总中断
}
//****************************************//
// 串口初始化 //
//****************************************//
void UART_init(void)
{
SM0 = 0; //选择串口为方式1工作
SM1 = 1; //8位数据波特率可变
REN = 1;
BRT = 0xDC;
AUXR = 0x15; //选择独立波特率发生器为串行
//口的波特率发生器,模式为1T
}
//******************************************//
// 转换结果计算 //
//******************************************//
double Result_Calculate(void)
{
uint temp;
double result;
temp = ADC_RES * 256 + ADC_RESL;
result = temp * 4.94 / 1024;
return result;
}
//******************************************//
// 串口发送数据 //
//******************************************//
void SendData( uchar byte )
{
SBUF = byte;
while(!TI);
TI = 0;
}
//******************************************//
// 主程序 //
//******************************************//
void main()
{
Init_LCD();
AD_init();
UART_init();
while(1);
}
//******************************************//
// A/D中断服务 //
//*
*****************************************//
void AD_Service(void) interrupt 5
{
ADC_CONTR &= !ADC_FLAG; //清标志
Printf_Decimal(Result_Calculate());
ADC_RES = 0x00;
ADC_RESL = 0x00;
ADC_CONTR = ADC_POWER|Speed_2|ADC_START; //开始下一次转换 _nop_();
_nop_();
_nop_();
_nop_();
}
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit PSB = P0^4; //串/并行接口选择 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 ); //写命令
void 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的驱动程序*************/
//**********************************//
//* 名称: Delay_ms()
//* 功能: 实现软件延时
//* 输入: time - 时间参数
//* 输出: 无
//**********************************//
void Delay_ms( uint time )
{
uint t; //82,延时时间 = (time*1003+16)us
while(time--) //41,延时时间 = (time*499+16)us
{
for( t = 0; t < 41; t++ );
}
STC12C5A60S2单片机各个模块程序代码13_stc12c5a60s2
}
//**********************************//
//* 名称: Busy()
//* 功能: 读取忙状态
//* 输入: 无
//* 输出: 1-忙 0-空闲
//**********************************//
uchar Busy(void)
{
uchar busy,flag;
Delay_ms(1);
busy = Read_Status();
if( busy & 0x80 )
flag = 1;
else
flag = 0;
Delay_ms(1);
return flag;
}
//**********************************//
//* 名称: Read_Status()
//* 功能: 读12864状态
//* 输入: 无
//* 输出: status-当前状态
//**********************************//
uchar Read_Status(void)
{
uchar status;
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 - 命令参数
//* 输出: 无
//**********************************//
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;
}
//**********************************//
//* 名称: 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 = 1;
Delay_ms(1);
E = 0;
_nop_();
_nop_();
}
//**********************************//
//* 名称: Read_Date()
//* 功能: 向12864读数据
//* 输入: 无
//* 输出: date - 返回的数据
//**********************************//
uchar Read_Date(void)
{
uchar date;
while(Busy()); //忙
RS = 1;
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
//* 输入: 无
//* 输出: 无
//**********************************//
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中的一个数
//* Y 只能是0-7中的一个数
//* 输出: 无
//**********************************//
void Location( uchar x, uchar y )
{
uchar position;
if( x == 1 )
x = 0x80;
else if( x == 2 )
x = 0x90;
else if( x == 3 )
x = 0x88;
else if( x == 4 )
x = 0x98;
position = x + y;
Write_Cmd(position);
Delay_ms(2);
}
//**********************************//
//* 名称: Clear_Screen()
//* 功能: 清屏
//* 输入: 无
//* 输出: 无
//**********************************//
void Clear_Screen(void)
{
Write_Cmd(0x34); //扩充指令
Delay_ms(11); //10ms
Write_Cmd(0x30); //基本指令
Delay_ms(1);
Write_Cmd(0x01);//清屏
Delay_ms(10);
}
//**********************************//
//* 名称: Write_str()
//* 功能: 向12864里写字符串
//* 输入: *p -- 字符串地址
//* 输出: 无
//**********************************//
void Write_str( uchar *p )
{
while( *p != '\0' )
{
Write_Date(*p);
p++;
}
}
//*********************************//
//* 名称:Printf_Decimal()
//* 功能:打印浮点类型数据
//* 输入:double Num --要打印的数据
//* 输出:无
//*********************************//
void Printf_Decimal(double Num)
{
uchar s[6] = {0,0,46,0,0};
uint t;
t = (uint)(Num * 1000);
s[0] = t/10000+48;
s[1] = t%10000/1000+48;
s[3] = t%1000/100+48;
s[4] = t%100/10+48;
s[5] = t%10+48;
Location(1,2);
Write_str(s);
SendData(s[0]);
SendData(s[1]);
SendData(s[2]);
SendData(s[3]);
SendData(s[4]);
SendData(s[5]);
SendData('\t');
}
//****************************************************************************//
// STC12C5
A60S2 PCA/PWM模块 //
//
// 说明: STC12C5A60S2单片机有两路可编程计数器阵列(PCA)模块,可用于软件
// 定时器,外部脉冲的捕捉、高速输出以及脉宽调制(PWM)输出 //
// 涉及寄存器:CMOD(PCA工作模式寄存器) CCON(PCA控制寄存器)
// CCAPM0,CCAPM1(PCA比较/捕获寄存器)
// CH,CL(PCA的16位计数器)、CCAPnL,CCAPnH(PCA捕捉/比较
寄存器)
// PCA_PWM0,PCA_PWM1(PCA模块PWM寄存器)
// AUXR1(辅助寄存器1)
// //
// 程序说明: 本程序实现对PCA/PWM模块的四种工作模式的测试。
//
// 注意:当选择相应的模式时,需在主函数内和中断服务内更改相应模式的初始
STC12C5A60S2单片机各个模块程序代码13_stc12c5a60s2
化
// 和相应的中断服务程序。去掉注释就可以,若要更改相应模式的功能,需在
相应
// 的初始化函数里更改相应的参数,脉宽调制(PWM)默认设置为无中断
方式
////****************************************************************************/
/
#include
#include
#define uchar unsigned char
#define uint unsigned int
/*******高速模式变量更改*********/
#define FOSC 12000000
#define T100KHz (FOSC/2/100000) //高速脉冲输出频率计算: f = PCA模块的时钟源
/(2*CCAP0L)
//CCAP0L = PCA时钟源/2/f
/*******定时模式变量更改*********/
#define T5ms (0.005*FOSC) //定时计数值=T/(1/PCA的时钟源)
/*******PWM模式变量更改**********/
#define DR_50 0x7f //50%占空比
#define DR_10 0x19 //10%占空比
/*******时钟源选择*******/
#define CLK_0 0x00 //Sysclk/12
#define CLK_1 0x02 //Sysclk/2
#define CLK_2 0x04 //定时器0的溢出脉冲
#define CLK_3 0x06 //ECI/P1.2(P4.1)输入的外部时钟
#define CLK_4 0x08 //Sysclk
#define CLK_5 0x0a //Sysclk/4
#define CLK_6 0x0d //Sysclk/6
#define CLK_8 0x0e //Sysclk/8
/********模式选择********/
#define H_model 0x4d //高速输出模式,中断模式
#define T_model 0x49 //定时模式
#define P_model 0x42 //无中断PWM模式
#define PL_model 0x63 //由低变高可中断PWM模式
#define PH_model 0x53 //由高变低可中断PWM模式
#define PHL_model 0x73 //高低都可中断PWM模式
#define CU_model 0x61 //16位捕获,上升触发中断模式
#define CD_model 0x51 //16位捕获,下降触发中断模式
#define CUD_model 0x71 //16位捕获,跳变触发中断模式
uint value = T100KHz; //100kHz时的CCAP0L值
uint time = T5ms; //5ms时的CCAP0L和CCAP0H值
uint test = 0; //测试用,要删除
sbit LED = P1^7; //用来观测定时模式和捕获模式的现象
//定时模式时500MS闪烁,捕获模式时捕获一次时取反
/*****函数声明*****/
void HP_init(void); //高速模式初始化
void PP_init(void); //PWM模式初始化
void TP_init(void); //定时器模式初始化
void CD_init(void); //捕
获模式初始化
//********************************//
// H_model初始化 //
//********************************//
void HP_init(void)
{
CMOD = CLK_4; //PCA时钟源为Sysclk
CCAPM0 = H_model; //高速输出模式
CCAP0L = value;
CCAP0H = value>>8;
value += T100KHz;
CR = 1; //开启PCA计数器
EA = 1; //开总中断
}
//********************************//
// P_model初始化 //
//********************************//
void PP_init(void)
{
CMOD = CLK_4; //时钟源为Sysclk
CCAPM0 = P_model; //无中断PWM模式
CCAP0L = DR_50; //%50占空比
CCAP0H = DR_50; //当CL值大于CCAP0L时输出为高,反之输出为低
//当CL溢出时CCAP0H的值装载到CCAP0L中
CR = 1; //开启PCA计数器
//当不使用定时0溢出为时钟源时,PWM输出的频率=PCA的时钟
源/256
//使用定时器溢出的时钟源时,可设定定时器的值对输出频率的改
变
//分频为0-256分频
}
//********************************//
// T_model初始化 //
//********************************//
void TP_init(void)
{
CMOD = CLK_4; //时钟源为Sysclk
CCAPM0 = T_model; //定时模式
CCAP0L = time; //
CCAP0H = time>>8; //定时5ms
time += T5ms;
CR = 1;
EA = 1;
}
//********************************//
// CD_model初始化 //
//********************************//
void CD_init(void)
{
CMOD = CLK_4;
CCAPM0 = CD_model;
CR = 1;
EA = 1;
}
//********************************//
// 主程序 //
//********************************//
void main()
{
CD_init();
//PP_init();
//HP_init();
//TP_init();
while(1)
{
}
}
//*******************************//
// 中断服务 //
//*******************************//
void CD_Service(void) interrupt 7
{
CCF0 = 0;
LED = ~LED;
}
/*void TP_Service(void) interrupt 7
{
CCF0 = 0; //清除PCA计数器溢出中断标志
test++;
if( test == 100 )
{
test = 0;
LED = ~LED;
}
CCAP0L = time;
CCAP0H = time>>8;
time += T5ms;
} */
/*
void HP_Service(void) interrupt 7
{
CCF0 = 0; //清除PCA计数器溢出中断标志
CCAP0L = value;
CCAP0H = value>>8;
value += T100KHz;
} */
//****************************************************************************//
// STC12C5A60S2串行通信模块 //
//
// 说明: STC12C5A60S2单片机有2个采用UART工作方式的全双工串行通信接
口
// 两个串口都有4种工作方式,两种波特率可变,两种波特率固定的
// 串口1为 TxD-P3.1引脚 RxD-P3.0引脚
// 串口2为 当在P1口时 TxD2-P1.3引脚 RxD2-P1.2引脚
// 当在P4口时 TxD2-P4.3引脚 RxD2-P4.2引脚
//
// 涉及寄存器:BRT(独立波特率发生器) AUXR(辅助寄存器)SCON(串行控制寄存器)
// SBUF(数据缓冲寄存器)PCON(电源控制寄存器)IE(中断控制寄存器)
// IP(中断优先级寄存器)IPH()SADEN()SADDR(
)WAKE_CLKO(时钟
唤醒寄存器)
// Bit1 - PD 控制单片机进入掉电模式
// //
// 程序说明: 程序实现从PC端发送数据到单片机,单片机将接收到的数据通过
12864
// 显示出来
//
//****************************************************************************//
#include
#include
#include "LCD.h"
#define uchar unsigned char
#define uint unsigned int
#define BTL 9600 //若要更改波特率直接更改此处,当波特率大于9600时需修改相应的接收程序,
//可选波特率有以下: 否则有可能出现乱码
//波特率为2400 //波特率为28800
//波特率为4800 //波特率为38400
//波特率为9600 //波特率为57600
//波特率为14400 //波特率为115200
//波特率为19200
uchar Send_Bflag = 0; //正在发送标志
uchar Receive_Bflag = 0; //正在接送标志
uchar Re;
sbit LED = P1^4;
sbit LED1 = P1^5;
void UART_init(void);
void Delay( uint time );
void Receive(void);
void Printf( uchar *p );
//****************************************//
// 串口初始化 //
//****************************************//
void UART_init(void)
{
SM0 = 0; //选择串口为方式1工作
SM1 = 1; //8位数据波特率可变
REN = 1;
#if( BTL == 2400 )
BRT = 0x70;
#elif( BTL == 4800 )
BRT = 0xB8;
#elif( BTL == 9600 )//波特率设置为9600
BRT = 0xDC;
#elif( BTL == 14400 )
BRT = 0xE8;
#elif( BTL == 19200 )
BRT = 0xEE;
#elif( BTL == 28800 )
BRT = 0xF4;
#elif( BTL == 38400 )
STC12C5A60S2单片机各个模块程序代码13_stc12c5a60s2
BRT = 0xF7;
#elif( BTL == 57600 )
BRT = 0xFA;
#elif( BTL == 115200 )
BRT = 0xFD;
#endif
AUXR = 0x15; //选择独立波特率发生器为串行
//口的波特率发生器,模式为1T
ES = 1; //允许串口中断
IPH = 0X10; //PSH = 1;
IP = 0X10; //PS = 1;串口1中断为最高优先级中断
EA = 1; //开总中断
}
//************************************************//
// 发送一个字节数据 //
//************************************************//
void Send_byte( uchar byte )
{
SBUF = byte;
while(!TI);
TI = 0;
}
//************************************************//
// 打印字符 //
//************************************************//
void Printf( uchar *p )
{
while( *p != '\0' )
{
Send_byte(*p);
p++;
}
}
//************************************************//
// 接收函数 //
//************************************************//
void Receive( void )
{
Write_Date(SBUF);
Re++;
if( Re == 16 )Location(2,0);
if( Re == 32 )Location(3,0);
if( Re == 48 )Location(4,0);
if( Re == 66 )
{
Re = 0;
Clear_Screen();
Location(1,0);
}
Receive_Bflag = 1;
}
//************************************************//
// 主函数 //
//*******************************************
*****//
void main()
{
Init_LCD();
UART_init();
while(1)
{
if( RI == 1 )
{
RI = 0;
Receive();
Printf("Success!");
}
if( TI == 1 )
{
TI = 0;
}
}
}
//***********************************************//
// 串口中断服务 //
//***********************************************//
void Com_Service(void) interrupt 4
{
EA = 0;
EA = 1;
}
//****************************************************************************//
// STC12C5A60S2 SPI接口模块
//
//
// 说明: STC12C5A60S2单片机提供一种高速串行通信接口SPI接口,SPI是一种全
// 双工.高速.同步的通信总线,有两种操作模式:主模式和从模式。
//
// 涉及寄存器:SPCTL(SPI控制寄存器)、SPSTAT(SPI状态寄存器)、SPDAT(数据寄
存器)
// AUXR1(辅助寄存器)
// //
// 程序说明: 本程序为SPI的主机程序,主机通过从串口接收数据并将数据通过SPI
// 传输给SPI的从机。 //****************************************************************************//
#include
#include
#define uchar unsigned char
#define uint unsigned int
/************对SPCTL寄存器的设置位宏定义*************/
#define SSIG 0x80 //SS引脚忽略
#define SPEN 0x40 //SPI使能位
#define DORD 0x20 //SPI数据发送LSB最先发送
#define MSTR 0x10 //主从模式选择
#define CPOL 0x08 //SPICLK空闲时为高电平
#define CPHA 0x04 //数据在SPICLK的前时钟沿驱动,并在后时钟沿采样
#define SP_CLK0 0x00 //SPI时钟频率为CPU_CLK/4
#define SP_CLK1 0x01 //SPI时钟频率为CPU_CLK/16
#define SP_CLK2 0x02 //SPI时钟频率为CPU_CLK/64
#define SP_CLK3 0x03 //SPI时钟频率为CPU_CLK/128
/************对SPSTAT寄存器的设置位宏定义************/
#define SPIF 0x80 //传输完成标志
#define WCOL 0x40 //SPI写冲突标志
/************SPI口切换宏定义***************/
#define SPI_P4 0x20 //SPI从P1口切换到P4口
sbit SPISS = P0^0; //用来选择从机
/************串口波特率设定*************************/
#define BTL 9600 //若要更改波特率直接更改此处,当波特率大于9600时需修改相应的
接收程序,
//可选波特率有以下: 否则有可能出现乱码
//波特率为2400 //波特率为28800
//波特率为4800 //波特率为38400
//波特率为9600 //波特率为57600
//波特率为14400 //波特率为115200
//波特率为19200
void UART_init(void);
uchar Receive(void);
void Printf( uchar *p );
void Init_SPI(void);
void Send_byte( uchar byte );
//****************************************//
// 串口初始化 // //****************************************//
void UART_init(void)
{
// SM0 = 0; //选择串口为方式1工作
// SM1 = 1; //8位数据波特率可变
// REN = 1; //允许串口接收
SCON = 0x50;
#if( BTL == 2400 )
BRT = 0
x70; //波特率设置为9600
#elif( BTL == 4800 )
BRT = 0xB8;
#elif( BTL == 9600 )
BRT = 0xDC;
#elif( BTL == 14400 )
BRT = 0xE8;
#elif( BTL == 19200 )
BRT = 0xEE;
#elif( BTL == 28800 )
BRT = 0xF4;
#elif( BTL == 38400 )
BRT = 0xF7;
#elif( BTL == 57600 )
BRT = 0xFA;
#elif( BTL == 115200 )
BRT = 0xFD;
#endif
AUXR = 0x15; //选择独立波特率发生器为串行
//口的波特率发生器,模式为1T
// ES = 1; //允许串口中断
// IPH = 0X10; //PSH = 1;
// IP = 0X10; //PS = 1;串口1中断为最高优先级中断
// EA = 1; //开总中断
}
//************************************************//
// 发送一个字节数据 //
//************************************************//
void Send_byte( uchar byte )
{
SBUF = byte;
while(!TI);
TI = 0;
}
//************************************************//
// 打印字符 // //************************************************// void Printf( uchar *p )
{
while( *p != '\0' )
{
Send_byte(*p);
p++;
}
}
//************************************************// // 接收函数 // //************************************************// uchar Receive( void )
{
uchar byte;
_nop_();
_nop_();
_nop_();
_nop_();
if( RI == 1 )
{
RI = 0;
byte = SBUF;
}
return byte;
}
//***********************************//
//* 名称:Init_SPI()
//* 功能: 对SPI进行初始化
//* 输入:无
//* 输出:无
//***********************************//
void Init_SPI(void)
{
SPDAT = 0; //清空数据寄存器
SPSTAT = SPIF|WCOL; //清空SPI状态寄存器
STC12C5A60S2单片机各个模块程序代码13_stc12c5a60s2
SPCTL = SPEN|MSTR; //SPI设置为主机模式
IE2 = 0x02; //允许SPI中断
}
//***********************************//
//* 名称:main
//* 功能:
//* 输入:无
//* 输出:无
//***********************************//
void main()
{
uchar flag = 0;
UART_init();
Init_SPI();
EA = 1; //开总中断
while(1)
{
flag = Receive();
if(flag) //当PC端有发送数据时才进行SPI传输数据
{
SPISS = 0;
SPDAT = flag;
flag = 0;
}
}
}
//***********************************//
//* 名称:SPI_ISR()
//* 功能: SPI中断服务
//* 输入:无
//* 输出:无
//***********************************//
void SPI_ISR(void) interrupt 9 using 1 //使用工作寄存器组1
{
SPSTAT = SPIF|WCOL; //清标志
Printf("Send_Data:");
Send_byte(SPDAT); //从从机中把主机上一次发送的值读回来
Send_byte('\t');
SPISS = 1;
}
//****************************************************************************//
// STC12C5A60S2 SPI接口模块 //
//
// 说明: STC12C5A60S2单片机提供一种高速串行通信接口SPI接口,SPI是一种全
// 双工.高速.同步的通信总线,有两种操作模式:主模式和从模式。
//
// 涉及寄存器:SPCTL(SPI控制寄存器)、SPSTAT(SPI状态寄存器)、SPDAT(数据寄
存器)
// AUXR1(辅助寄存器)
// //
// 程序说明: 本程序为SPI的从机程序,从机通过SPI接收主机发送过来的数据,并通
过串口
// 显示到PC端,
//
//****************************************************************************//
#include
#include
#define uchar unsigned char
#define uint unsigned int
/************对SPCTL寄存器的设置位宏定义*************/
#define SSIG 0x80 //SS引脚忽略
#define SPEN 0x40 //SPI使能位
#define DORD 0x20 //SPI数据发送LSB最先发送
#define MSTR 0x10 //主从模式选择
#define CPOL 0x08 //SPICLK空闲时为高电平
#define CPHA 0x04 //数据在SPICLK的前时钟沿驱动,并在后时钟沿采样
#define SP_CLK0 0x00 //SPI时钟频率为CPU_CLK/4
#define SP_CLK1 0x01 //SPI时钟频率为CPU_CLK/16
#define SP_CLK2 0x02 //SPI时钟频率为CPU_CLK/64
#define SP_CLK3 0x03 //SPI时钟频率为CPU_CLK/128
/************对SPSTAT寄存器的设置位宏定义************/
#define SPIF 0x80 //传输完成标志
#define WCOL 0x40 //SPI写冲突标志
/************SPI口切换宏定义***************/
#define SPI_P4 0x20 //SPI从P1口切换到P4口
/************波特率选择********************/
#define BTL 9600 //若要更改波特率直接更改此处,当波特率大于9600时需修改相应的接
收程序,
//可选波特率有以下: 否则有可能出现乱码
//波特率为2400 //波特率为28800
//波特率为4800 //波特率为38400
//波特率为9600 //波特率为57600
//波特率为14400 //波特率为115200
//波特率为19200
void UART_init(void);
uchar Receive(void);
void Printf( uchar *p );
void Init_SPI(void);
void Send_byte( uchar byte );
//****************************************//
// 串口初始化 // //****************************************//
void UART_init(void)
{
// SM0 = 0; //选择串口为方式1工作
// SM1 = 1; //8位数据波特率可变
// REN = 1; //允许串口接收
SCON = 0x50;
#if( BTL == 2400 )
BRT = 0x70; //波特率设置为9600
#elif( BTL == 4800 )
BRT = 0xB8;
#elif( BTL == 9600 )
BRT = 0xDC;
#elif( BTL == 14400 )
BRT = 0xE8;
#elif( BTL == 19200 )
BRT = 0xEE;
#elif( BTL == 28800 )
BRT = 0xF4;
#elif( BTL == 38400 )
BRT = 0xF7;
#elif( BTL == 57600 )
BRT = 0xFA;
#elif( BTL == 115200 )
BRT = 0xFD;
#endif
AUXR = 0x15; //选择独立波特率发生器为串行
//口的波特率发生器,模式为1T
// ES = 1; //允许串口中断
// IPH = 0X10; //PSH = 1;
// IP = 0X10; //PS = 1;串口1中断为最高优先级中断
// EA = 1; //开总中断
}
//************************************************//
// 发送一个字节数据 //
//************************************************//
void Send_byte( uchar byte )
{
SBUF = byte;
while(!TI);
TI = 0;
}
//************************************************//
// 打印字符 //
//************************************************//
void Printf( uchar *p )
{
while( *p != '\0' )
{
Send_byte(*p);
p++;
}
}
//************************************************//
// 接收函数 //
//************************************************//
uchar Receive( void )
{
uchar byte;
_nop_();
_nop_();
_nop_();
_nop_();
if( RI == 1 )
{
RI = 0;
byte = SBUF;
}
return byte;
}
//***********************************//
//* 名称:Init_SPI()
//* 功能: 对SPI进行初始化
//* 输入:无
//* 输出:无
//***********************************//
void Init_SPI(void)
{
SPDAT = 0; //清空数据寄存器
SPSTAT = SPIF|WCOL; //清空SPI状态寄存器
SPCTL =SPEN; //SPI设置为从机模式
IE2 = 0x02; //允许SPI中断
}
//***********************************//
//* 名称:main
//* 功能:
//* 输入:无
//* 输出:无
//***********************************//
void main()
{
uchar flag = 0;
UART_init();
Init_SPI();
EA = 1; //开总中断
while(1)
{
flag = Receive();
if(flag) //当PC端有给从机发送数据时把从机当前的SPDAT值发送出来
{
Send_byte(SPDAT);
flag = 0;
}
}
}
//***********************************//
//* 名称:SPI_ISR()
//* 功能: SPI中断服务
//* 输入:无
//* 输出:无
//***********************************//
void SPI_ISR(void) interrupt 9 using 1 //使用工作寄存器组1
{
SPSTAT = SPIF|WCOL; //清标志
Printf("Receive_Data:");
P2 = P2+1; //LED灯表示接收的次数
Send_byte(SPDAT); //读出主机发送过来的数据
SPDAT = SPDAT; //把上一次接收到的值传回主机
Send_byte('\t');
}