STC12C5A60S2编程
STC12C5A60S2教程
特殊单元
0003H 外部中断0中断服务程序的入口地址 000BH 定时/计数器0中断服务程序的入口地址 0013H 外部中断1中断服务程序的入口地址 001BH 定时/计数器1中断服务程序的入口地址 0023H 串行通信口1中断服务程序的入口地址 002BH ADC中断服务程序的入口地址 0033H 低电压检测中断服务程序的入口地址 003BH PCA中断服务程序的入口地址 0043H 串行通信口2中断服务程序的入口地址 004BH SPI中断服务程序的入口地址 读取程序存储器中保存的表格常数等内容时,使用MOVC指令。
0592mhz电容c1c2的典型值是47pfxtal1gnd22stc12c5a60s222stc12c5a60s2单片机的结构单片机的结构221stc12c5a60s2221stc12c5a60s2单片机的内部结构单片机的内部结构ram地址寄存器ram电源监控上电复位上电复位掉电复位可配置io口p0p4可配置io口p5程序flash程序地址寄存器缓冲器堆栈指针pc增量器pcpcb寄存器acctmp2tmp11k字节eepomrstale定时和控制逻辑片内rc振荡器dptr硬件看门狗wdt8通道高速adspi2路pwmpcaccu捕获比较单元指令寄存器可配置振荡器alupsw中断uart定时器逻辑xtal1xtal2cpu时钟222cpu以8位算术逻辑运算部件alu为核心加上通过内部总线而挂在其周围的暂存器tmp1tmp2累加器acc寄存器b程序状态标志寄存器psw以及布尔处理机就组成了整个运算器的逻辑电路
FFH 特殊功能寄存器区(80H~FFH) ~ [只能直接寻址访问] 80H 7FH 通用用户RAM和堆栈区(30H~7FH) ~ 30H [可直接或间接字节寻址] 2FH 位寻址区(16字节,共128位) ~ 也可以字节寻址 20H 1FH~ 18H 3区(R7~R0) 2区(R7~R0) 17H~ 10H 4个工作寄存器区 也可做RAM单元使用 0FH~ 08H 1区(R7~R0) 07H~ 00H 0区(R7~R0) 80H~ FFH [只能间接寻址访问 ]
STC12C5A60S2定时器,STC12C5A60S2定时器程序
加代码。
STC12C5A60S2单片机集成了两个16位定时/计数器。
1)寄存器
1.1)TMOD定时器工作方式控制寄存器,包括13位寄存器、16位
寄存器、8位寄存器等;
1.2)TCON定时器控制寄存器,主要包括定时器启动控制位等;
1.3)AUXR辅助寄存器,用以设置分频;默认12分频
1.4)TH0/1:定时器高8位寄存器
1.5)TL0/1:定时器低8位寄存器
定时器计算
STC12C5A60S2系列是1T的8051单片机,为了兼容传统的8051,
定时器0和定时器1复位后是传统8051的速度,既12分频,这是为了兼容
传统8051。但也可以不进行12分频,实现真正的1T。
编译、下载目标代码,LED灯以1s间隔闪烁,说明我们的代码是正
STC12C5A60S2定时器,STC12C集成了共4个16位定时器,两个与传统8051
兼容的定时器/计数器,16位定时器T0和T1,没有定时器2,但有独立波特
率发生器做串行通讯的波特率发生器,再加上2路PCA模块可再实现2个
16位定时器;
1.基本特性
单片机STC12C5A60S2控制AT24C04的程序(C语言)
void Delay5ms()
{
WORD n = 2500;
while(n--)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/**************************************
起始信号
**************************************/
void AT24C04_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
SDA = 1; //产生上升沿
*******************************
发送应答信号
入口参数:ack(0:ACK 1:NAK)
**************************************/
void AT24C04_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
/**************************************
接收应答信号
**************************************/
STC12C5A60S2单片机c语言程序代码调试例程
//12T指的是每12个时钟加1与普通C51一样
//允许将P3.5/T1脚配置为定时器1的时钟输出CLKOUT1,只
能工作在定时器模式2下
//T1工作在1T模式时的输出频率 = SYSclk/(256-TH0)/2
//T1工作在12T模式时的输出频率 = SYSclk/12/(256-TH0)/2
//工作模式为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 )
void Delay_ms( uint time )
{
uint t; //延时时间 = (time*1003+16)us while(time--)
{
for( t = 0; t < 82; t++ );
}
}
//***********************************//
//1T指的是每1个时钟加1,是普通C51的12倍
//12T指的是每12个时钟加1与普通C51一样
AUXR = 0xc0; //T0定时器速度是普通8051的12倍,即工作在1T模式下
//T1定时器速度是普通8051的12倍,即工作在1T模式下
TMOD = 0x22; //定时器0工作模式为方式2,自动装载时间常数
#define uchar unsigned char
stc12c5a60s2 AD 程序
#define ADC_SPEEDLL 0x00 //540 clocks
#define ADC_SPEEDL 0x20 //360 clocks
#define ADC_SPEEDH 0x40 //180 clocks
#define uchar unsigned char
#define uint unsigned int
/*LCD 各种端口的设置 */
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
sbit LCD_PSB=P2^3;
#define ADC_POWER 0x80 //ADC电源控制位
#define ADC_FLAG 0x10 //ADC完成标志
#define ADC_START 0x08 //ADC开始标志位。
/*可写入 4*8 汉字,x的范围是1到4,y的范围是1到8*/
void lcd_string(uchar x,uchar y,char*str)
{
static uchar flag = 0;
uchar i = 0;
if(!flag)
{
lcd_init();
flag = 1;
case 3 : temp = 0x88;
break;
case 4 : temp = 0x98;
break;
default : temp = 0x80;
break;
}
pos = temp + col-1;
LCD_0(0,pos);
}
}
/*字符位置的选定*/
STC12C5A60S2教程
程序状态标志寄存器PSW:
D7 CY
D6 AC
D5 D4 D3 D2 F0 RS1 RS0 OV
D1 F1
D0 P
CY:进位标志位 当执行加/减法指令时,如果操作结果的最高位D7出现进/借位,则CY置 “1”,否则清零。此外,CPU在进行移位操作时也会影响这个标志位。 AC:辅助进位标志位 当执行加/减法指令时,如果低四位数向高四位数产生进/借位,则AC置 “1”,否则清零。 F0:用户标志0 该位是由用户定义的一个状态标志。 RS1,RS0:工作寄存器组选择控制位 OV:溢出标志位 指示运算过程中是否发生了溢出。 F1:用户标志1 该位是由用户定义的一个状态标志。 P:奇偶标志位 如果累加器ACC中1的个数为偶数,P=0;否则P=1。
2)位寻址区
20H~2FH之间的单元既可以像普通RAM单元一样按字节存取,也可以 对单元中的任何一位单独存取,共128位,所对应的位地址范围是00H~ 7FH。特殊功能寄存器中,直接地址可被8整除的寄存器(除了IP.7、IP.6 和IE.6以外)也可以进行位寻址。 可进行位寻址的单元,请见教材图2-8和图2-9.
常见的晶振连接方法
C2
STC12C5A60S2
XTAL2
C1
M XTAL1 GND
晶体振荡器M的典型值是11.0592MHz,电 容C1、C2的典型值是47Pf。
2.2 STC12C5A60S2单片机的结构
2.2.1 STC12C5A60S2单片机的内部结构
RAM 可配置 I/O口 可配置 I/O口 地址 RAM 1K字节 EEPOM P0~P4 P5 寄存器 程序 FLASH 程序地址 寄存器 缓冲器 B 寄存器 电源监控 (上电复位、 掉电复位 ) RST ALE ACC T MP1 T MP2 ALU PSW 定时和 指令 控制逻辑 寄存器 硬件看门狗 (W DT ) 片内 RC 振荡器 SPI 中断、 UART 、 定时器逻辑 堆栈指针 PC 增量器 PC DPT R 8 通道 高速 A/D 2 路 PW M/PCA/CCU 捕获 / 比较单元
STC12C5A60S2教程
WR/P3.6 13
RD/P3.7 14 XTAL2 15
XTAL1 16
GND 17 SS/P4.0 18
A08/P2.0 19 A09/P2.1 20 A10/P2.2 21 A11/P2.3 22 A12/P2.4 23 P5.0 24
CLKOUT2/ADC0/P1.0 ADC1/P1.1 RxD2/EC1/ADC2/P1.2 TxD2/CCP0/ADC3/P1.3 SS/CCP1/ADC4/P1.4 MOSI/ADC5/P1.5 MISO/ADC6/P1.6 SCLK/ADC7/P1.7 P4.7/RST RxD/P3.0 TxD/P3.1 INT0/P3.2 INT1/P3.3 CLKOUT0/T0/P3.4 CLKOUT1/T1/P3.5 WR/P3.6 RD/P3.7 XTAL1 XTAL2 GND
常见的晶振连接方法
C2
STC12C5A60S2
XTAL2
C1
M XTAL1 GND
晶体振荡器M的典型值是11.0592MHz,电 容C1、C2的典型值是47Pf。
2.2 STC12C5A60S2单片机的结构
2.2.1 STC12C5A60S2单片机的内部结构
RAM 可配置 I/O口 可配置 I/O口 地址 RAM 1K字节 EEPOM P0~P4 P5 寄存器 程序 FLASH 程序地址 寄存器 缓冲器 B 寄存器 电源监控 (上电复位、 掉电复位 ) RST ALE ACC T MP1 T MP2 ALU PSW 定时和 指令 控制逻辑 寄存器 硬件看门狗 (W DT ) 片内 RC 振荡器 SPI 中断、 UART 、 定时器逻辑 堆栈指针 PC 增量器 PC DPT R 8 通道 高速 A/D 2 路 PW M/PCA/CCU 捕获 / 比较单元
STC12C5A60S2 双串口使用程序
STC12C5A60S2 双串口使用程序(已经验证成功)#include <stc12c5a60s2.h>#include "intrins.h"#define uchar unsigned char#define S2RI 0x01 // 串口2接收中断请求标志位#define S2TI 0x02 // 串口2发送中断请求标志位//================================================// 对于将P4.4、P4.5当做I/O口使用必须添加的定义||//================================================sfr p4sw=0xbb; // 需在主函数文件中做相应设置4、5、6为1(作为I/O口使用)/*sbit button1=P4^3;sbit button2=P4^4;sbit button3=P4^5;sbit button4=P4^6;*/uchar code temp1[]={" 白云:“我可是个名人”"};uchar code temp2[]={" 黑土:“啥名人啊,你就是个人名”"};uchar code temp3[]={" 小崔:“诶,大叔大妈,你俩都冷静冷静”"};uchar code temp4[]={" 观众:“哈哈哈哈”"};/*void delay_1ms(uchar ii) // 误差-0.018084490741us{unsigned char a,b;for(; ii>0; ii--)for( b = 18; b>0; b--)for( a = 152; a>0; a--);_nop_(); //if Keil,require use intrins.h}void delay1s(void) //误差-0.000000000125us{unsigned char a,b,c;for( c = 212; c>0; c--)for( b = 160; b>0; b--)for( a = 80; a>0; a--);_nop_(); //if Keil,require use intrins.h_nop_(); //if Keil,require use intrins.h}*///************************ 串口通信部分******************************uchar wj_uun = '!'; // 用于存放串口1接收的字符uchar wj_uun2 = '?'; // 用于存放串口2接收的字符void bt_uart_init() // 单片机双串口初始化{//SCON=0X50; // SM0=0 SM1=1 SM2=0 REN=1SM0 = 0; // 串口工作方式1:1位起始位,8位数据位,1位停止位允许串口接收SM1 = 1;REN = 1; // 允许串口接收//RI=1; // 接收标志位,0:正在接收1:接收完毕(如果RI=1就一直执行串口中断) TMOD = 0X20; // 定时器T1工作方式2TH1 = 0XFD; // 9600bit/s下的定时器初值TL1 = 0XFD;TR1 = 1; // 启动定时器T1EA = 1; // 开总中断ES = 1; // 开串行口中断S2CON = 0x50; // 串口2工作在方式1 10位异步收发S2SM0=0 S2SM1=1 S2REN=1允许接收BRT = 0XFD; // 9600bit/s下的独立波特率发生器初值AUXR = 0x10; // 辅助寄存器:0001 0000 ->BRTR=1:独立波特率发生器开始计数,S2SMOD=0:波特率不加倍,BRTx12=0:独立波特率每12个时钟计数一次IE2 = 0x01; // 开串口2中断0000 0001->ES2=1// AUXR1 = 0x10; // 0001 0000->S2_P4=1:UART2从P1口(RxD2:P1.2 TxD2:P1.3)切换到P4口(RxD2:P4.2 TxD2:P4.3) 否则默认都为P1口}/************** 串口1发送函数*****************/void s1_send_char(uchar dat) // 发送端(发送的是字符){SBUF = dat; // 将字符送入发送缓冲寄存器while(!TI); // TI为发送状态标志位,0:发送中1:发送结束TI = 0; // 手动清零标志位}void s1_send_string(uchar *pt) // 通过调用发送字符函数来发送字符数组{while(*pt != '\0'){s1_send_char(*pt++);}}/************** 串口2发送函数*****************/void s2_send_char(uchar dat2) // 发送端(发送的是字符){S2BUF = dat2; // 将字符送入串口2的发送缓冲寄存器while(!(S2CON&S2TI)); // 判断发送是否结束:S2CON.bit2 = 0:发送中1:发送结束S2CON &= ~S2TI; // 手动清零标志位,令S2CON.bit2 = 0}void s2_send_string(uchar *pt2) // 通过调用发送字符函数来发送字符数组{while(*pt2!='\0'){s2_send_char(*pt2++);}}/************** 串口1中断程序*****************/void bt_serial_1() interrupt 4 // 中断编号4为串行口1中断{if(RI) // 接收标志位,0:正在接收1:接收完毕(如果RI=1就一直执行中断){RI = 0; // 同样需要手动清零wj_uun = SBUF; // 将接收缓冲器接收的字符送入变量中}}/************** 串口2中断程序*****************/void bt_serial_2() interrupt 8 // 中断编号8为串行口2中断{if(S2CON&S2RI) // 接收标志位: S2CON.bit1 = 0:正在接收1:接收完毕(如果RI=1就一直执行中断){S2CON &= ~S2RI; // 同样需要手动清零,令S2CON.bit1 = 0wj_uun2 = S2BUF; // 将串口2接收到的字符送入变量中}}void main(void){bt_uart_init(); // 串口初始化p4sw = 0x70; // 0111 0000 对应的4、5、6脚设置成功通用I/O口while(1){/*if(wj_uun != '!') // 串口1接收{s1_send_char(wj_uun); // 串口1发送wj_uun = '!';}*/if(wj_uun2 != '?') // 串口2接收{s2_send_char(wj_uun2); // 串口2发送wj_uun2 = '?';}}}。
STC12C5A60S2头文件函数程序
//--------------------------------------------------------------------------------//新一代1T 8051系列单片机内核特殊功能寄存器C51 Core SFRs// 7 6 5 4 3 2 1 0 Reset Valuesfr ACC = 0xE0; //Accumulator 0000,0000sfr B = 0xF0; //B Register 0000,0000sfr PSW = 0xD0; //Program Status Word CY AC F0 RS1 RS0 OV F1 P 0000,0000//-----------------------------------sbit CY = PSW^7;sbit AC = PSW^6;sbit F0 = PSW^5;sbit RS1 = PSW^4;sbit RS0 = PSW^3;sbit OV = PSW^2;sbit P = PSW^0;//-----------------------------------sfr SP = 0x81; //Stack Pointer 0000,0111sfr DPL = 0x82; //Data Pointer Low Byte 0000,0000sfr DPH = 0x83; //Data Pointer High Byte 0000,0000//--------------------------------------------------------------------------------//新一代1T 8051系列单片机系统管理特殊功能寄存器// 7 6 5 4 3 2 1 0 Reset Valuesfr PCON = 0x87; //Power Control SMOD SMOD0 LVDF POF GF1 GF0 PD IDL 0001,0000// 辅助寄存器7 6 5 4 3 2 1 0 Reset Valuesfr AUXR = 0x8E; //Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS 0000,0000//-----------------------------------sfr AUXR1 = 0xA2; //Auxiliary Register 1 - PCA_P4 SPI_P4 S2_P4 GF2 ADRJ - DPS 0000,0000/*PCA_P4:0, 缺省PCA 在P1 口1,PCA/PWM 从P1 口切换到P4 口: ECI 从P1.2 切换到P4.1 口,PCA0/PWM0 从P1.3 切换到P4.2 口PCA1/PWM1 从P1.4 切换到P4.3 口SPI_P4:0, 缺省SPI 在P1 口1,SPI 从P1 口切换到P4 口: SPICLK 从P1.7 切换到P4.3 口MISO 从P1.6 切换到P4.2 口MOSI 从P1.5 切换到P4.1 口SS 从P1.4 切换到P4.0 口S2_P4:0, 缺省UART2 在P1 口1,UART2 从P1 口切换到P4 口: TxD2 从P1.3 切换到P4.3 口RxD2 从P1.2 切换到P4.2 口GF2: 通用标志位ADRJ:0, 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器1,10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器DPS: 0, 使用缺省数据指针DPTR01,使用另一个数据指针DPTR1*///-----------------------------------sfr WAKE_CLKO = 0x8F; //附加的SFR WAK1_CLKO/*7 6 5 4 3 2 1 0 Reset ValuePCAWAKEUP RXD_PIN_IE T1_PIN_IE T0_PIN_IE LVD_WAKE _ T1CLKO T0CLKO 0000,0000Bb7 - PCAWAKEUP : PCA 中断可唤醒powerdown。
STC12C5A60S2单片机PWM程序
STC12C5A60S2单片机PWM程序两个头文件main.c#include <REG51.H>#include <intrins.h>#define U8 unsigned char#define U16 unsigned intvoid DelayMs(U8 ms);void PWM_clock(U8 clock); void PWM_start(U8 module,U8 mode);////////////////////// 延时子程序/////////////////////////////void DelayMs(U8 ms) // 在11.0592M 晶振下,stclOf 系列(单周期指令)的ms 级延时{U16 i;while(ms--){for(i = 0; i < 850; i++); }}//////////////////// 主函数入口////////////////////////////sfr CCON = 0xD8; //PCA 控制寄存器sfr CMOD = 0xD9; //PCA 模式寄存器sfr CCAPM0 = 0xDA; //PCA 模块0模式寄存器// 模块0对应P1.3/CEX0/PCA0/PWM0(STC12C5A60系列)sfr CCAPM1 = 0xDB; //PCA 模块1 模式寄存器// 模块1 对应P1.4/CEX1/PCA1/PWM1(STC12C5A60系列)sfr CL = 0xE9; //PCA 定时寄存器低位sfr CH = 0xF9; //PCA 定时寄存器高位sfr CCAP0L = 0xEA; //PCA 模块0的捕获寄存器低位sfr CCAP0H = 0xFA;//PCA模块0的捕获寄存器高位sfr CCAP1L = OxEB; //PCA 模块1的捕获寄存器低位sfr CCAP1H = 0xFB; //PCA 模块1的捕获寄存器高位sfr PCA_PWM0 = 0xF2; //PCA PWM 模式辅助寄存器0sfr PCA_PWM1 = 0xF3; //PCA PWM 模式辅助寄存器1sbit CF = 0xDF; //PCA 计数溢出标志位sbit CR = 0xDE; //PCA 计数器运行控制位sbit CCF1 = 0xD9; //PCA 模块1 中断标志sbit CCF0 = 0xD8; //PCA 模块0 中断标志//* CCAPOH = CCAPOL = 0XC0; // 模块0 输出占空因数为25%//* CCAPOH = CCAPOL = 0X80; // 模块0 输出占空因数为50%//* CCAPOH = CCAPOL = 0X40; // 模块0 输出占空因数为75%void PWM_clock(U8 clock);void PWM_start(U8 module,U8 mode);void PWM_clock(U8 clock){CMOD |= (clock<<1);CL = 0x00;CH = 0x00;void PWM_start(U8 module,U8 mode,U8 zkb) {CCAP0L = 0XC0;CCAP0H = 0XC0; // 模块 0 初始输出 占空因数为 25% CCAP1L = 0XC0; CCAP1H = 0XC0; // 模块 1 初始输出 占空因数为 25% if(module==0) {中断default: break;}}elseif(module==1){switch(mode){ switch(mode){case 0: CCAPM0 = 0X42;break; //case 1: CCAPM0 = 0X53;break; //中断case 2: CCAPM0 = 0X63;break; //中断case 3: CCAPM0 = 0X73;break; //模块0设置为8位PWM 输出,无中断 模块0设置为8位PWM 输出,下降沿产生 模块0设置为8位PWM 输出,上升沿产生case 0: CCAPM0 = CCAPM1 = 0X42;break; //出,无中断case 1: CCAPM0 = CCAPM1 = 0X53;break; //出,下降沿产生中断case 2: CCAPM0 = CCAPM1 = 0X63;break; //出,上升沿产生中断case 3: CCAPM0 = CCAPM1 = 0X73;break; //出,跳变沿产生中断default: break; case 0: CCAPM1 = 0X42;break; //case 1: CCAPM1 = 0X53;break; //中断case 2: CCAPM1 = 0X63;break; // 中断 case 3: CCAPM1 = 0X73;break; //中断default: break;}}elseif(module==2){switch(mode){模块1设置为8位PWM 输出,无中断 模块1设置为8位PWM 输出,下降沿产生 模块1设置为8位PWM 输出,上升沿产生模块0和1设置为8位PWM 输模块0和1设置为8位PWM 输 模块0和1设置为8位PWM 输 模块0和1设置为8位PWM 输}CR=1; //PCA 计数器开始计数}void PCA_Intrrpt(void) interrupt 7 {if(CCF0) CCF0=0;if(CCF1) CCF1=0; // 软件清零if(CF) CF=0; // 软件清零}void main(){TMOD|=0x02; /* timer 0 mode 2: 8-Bit reload */TH0=0xff;TR0=1;PWM_clock(2); // PCA/PWM 时钟源为定时器0 的溢出PWM_start(O,O); // 模块0,设置为PWM输出,无中断,初始占空因素为25% DelayMs(250);ITO=1; // 下降沿触发EXO=1; // 开中断OEA=1; // 开总中断while(1); // 等待中断产生,按下S15按键产生中断信号}#include "reg51.h"#define uchar unsigned char #define uint unsigned intsbit di=P3A7;uchar jishu=0x00; // 用来记录中断的次数void delay(uchar z){uchar i;for(i=0;i<z;i++);}/ """"""""""""""""""""""""""""""""""""// if n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n // 外部中断0 子函数void PWM_Select(void) interrupt 0 {U8 modjishu++; // 中断一次加1mod=jishu%3;switch(mod){case 0: CCAPM0 = 0X42;break; //0 设置为25%PW输出case 1: CCAPM0 = 0X53;break; //0 设置为50%PW输出case 2: CCAPM0 = 0X63;break; //0 设置为75%PW输出default: break;} delay(255);。
STC12C5A60S2内部PWM模块程序
//新一代1T 8051系列单片机PCA/PWM特殊功能寄存器
// 7 6 5 4 3 2 1 0 Reset Value
sfr CCON = 0xD8; //PCA控制寄存器。CF CR - - - - CCF1 CCF0 00xx,xx00
//-----------------------
STC12C5A60S2内部PWM模块程序
/**************************************************************
*******************************
说明:单片机的PCA_PWM使用,60S2只有两个PWM输出,分别是1.3
// 1 1 1 0 0 1 1 0x73 PWM输出由低变高或由高变低都可产生中断
//-----------------------
sfrCCAP0L=0xEA;//PCA模块0的捕捉/比较寄存器低8位。0的捕捉/比较寄存器高8位。
0000,0000
sfrCCAP1L=0xEB;//PCA模块1的捕捉/比较寄存器低8位。
0000,0000
sfrCCAP1H=0xFB;//PCA模块1的捕捉/比较寄存器高8位。
0000,0000
//-----------------------
// 7 6 5 4 3 2 1 0 Reset Value
sfrPCA_PWM0=0xF2;//PCA模块0PWM寄存器。------EPC0H
EPC0L xxxx,xx00
sfrPCA_PWM1=0xF3;//PCA模块1PWM寄存器。------EPC1H
用stc12c5a60s2单片机采集交流电压并计算其有效值(普中科技hc6800为硬件)
用stc12c5a60s2单片机采集交流电压并计算其有效值(普中科技hc6800为硬件)//******P1^7为参考电压,P1^2为待测电压接口#include<reg51.h>#include<math.h>#define bianshu 1#define qshu 50#define buchangTH1 0Xfe#define buchangTL1 0X0c //1000us 1000hz 10000us 考虑给取值过程留点时间(200us) 用700us 65536-700=64836 //与ad相关的特殊功能寄存器sfr ADC_CONTR =0XBC; //定义ad相关特殊功能寄存器地址sfr ADC_RES =0XBD;sfr ADC_RESL =0XBE;sfr P1ASF =0X9D;sbit EADC=IE^5;//ad中断允许位//配合ADC_CONTR置相应位因为ADC_CONTR不可位寻址,所以采用与或方式置相应位#define ADC_POWER 0X80#define ADC_FLAG 0X10#define ADC_START 0X08#define ADC_SPEEDLL 0X00#define ADC_SPEEDL 0X20#define ADC_SPEEDH 0X40#define ADC_SPEEDHH 0X60unsigned char CH2=2;//通道 p1^2unsigned char CH7=7;//通道 p1^7//***步长所用变量int Gbuchang,Lbuchang;//***遍数,取数个数,开断及等待控制部分所用变量char N=qshu,M=bianshu;char kd,bx;char flag1; //等待标志位,用作等待开断、定时//***取数部分所用变量float bus,zhi[qshu],cankao;char i,geshu;//***处理数据部分所用变量char u,v,w;//for循环控制位float zhi1[qshu],zhi2[qshu],sum;//改成float了,少占点内存要取的 n个数(转换完的整数)float junzhi;int zhenzhi,zhi3[qshu];//***显示部分所用变量char j,k,s;//for循环控制位int LedNumVal;char LedOut[8]; //取要显示数的个十百... 数码管8位unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码sbit LS138A = P2^2; //定义138译码器的输入A脚由P2.2控制控制8个数码管sbit LS138B = P2^3; //定义138译码器的输入脚B由P2.3控制sbit LS138C = P2^4; //定义138译码器的输入脚C由P2.4控制//***查错部分所用变量sbit cha1=P2^0;sbit cha2=P2^1;sbit cha3=P2^7;sbit cha4=P2^6;void delay(int q);void main(){while(1){//***遍数,取数个数,开断及等待控制部分所用变量M=bianshu;N=qshu;bx=0;//显示遍数标志位kd=0;//开断标志位flag1=1;//用“1”符合逻辑!控制开始与结束标志位CH2=2;//通道 p1^2 辅助置ADC_CONTR的通道位CH7=7;//通道 p1^2 辅助置ADC_CONTR的通道位//***取数部分所用变量bus=0;//数据传输媒介(实数)数据区cankao=0;geshu=0;sum=0;junzhi=0;zhenzhi=0;i=0;//i是取数中的变量u=0;//j,k,s都是显示程序中的变量v=0;w=0;j=0;//j,k,s都是显示程序中的变量k=0;s=0;LedNumVal=0;//**********zhi[i]清零************for(i=0;i<N;i++){zhi[i]=0;zhi1[i]=0;zhi2[i]=0;zhi3[i]=0;}//********ad初始化********EADC=1; //允许ad中断P1ASF=0x84; //通道1000 0100ADC_RES=0; //寄存器清零ADC_CONTR=ADC_POWER|ADC_SPEEDHH|CH2;//设置电源速度通道2 注意此处不开启ADC_START 取完数之后每次都需要再置位delay(1); //第一次需要时间来置位//********外部中断1初始化********EX1=1; //外部中断1允许中断号2 引脚P3^3IT1=1; //设置为下降沿触发//********定时器1初始化(采用查询方式)所以没有开启定时器1的中断允许位ET1位TMOD=0X11; //0001 0001 定时1,0 方式1 16位Gbuchang=buchangTH1;Lbuchang=buchangTL1;TH1=Gbuchang;TL1=Lbuchang; //1000us 无定时器中断允许采用查询方式控制步长// 用定时器0来查看一下取数时间TH0=0;TL0=0;//*****取数要求:ad从零点开始,按相同步长取到确定的N个数***************************EA=1;//等待外部中断1来开启ad与定时器1//****flag1=1(等待同步方波下降沿开启)>>flag1=0(采集数据)>>flag1=1(等待同步方波下降沿关闭)>>//*******ad取数阶段**********要保证下次循环不被打扰//通道二:取zhi[i](要为小数),由同步方波确定取值“geshu”个//通道七:取cankao,cankao为标准电压的数字量//涉及数据:zhi[i],geshu,cankaowhile(flag1==1);TR0=1;cha3=0;while(flag1==0){cha4=0;for(i=0;i<N;i++) //ad转换完一次后ADC_START会自动清零{TR1=1; //此处开启定时器开始定时器控制步长ADC_CONTR|=ADC_START; //此处开启ad转换统一开始时间开始ad 时间很短while(TF1==0); //因为步长大于ad采集时间,所以此处会进入ad中断取!!ADC_RES》bus!!等待定时器控制步长完再把数bus>>zhi[i]TF1=0;//软件查询,需软件清中断申请位TR1=0;//此处关闭为了不让它再计时***定时器计满溢出回零之后(方式0、1、3)会重新开始从零计数所以要先关闭再说 **** TH1=Gbuchang;TL1=Lbuchang;zhi[i]=bus;//zhi[i]为初始取的数字量bus=0;//清零geshu=i+1;//指向i的下一个数标if(flag1==1)// 此处本意是想:用同步方波来控制取数的结束时间,而不是以前的固定取N个数在等待结束break;}TR0=0;//取完通道二(一个周期后)就要关闭定时器0的TR0ADC_CONTR=ADC_POWER|ADC_SPEEDHH|CH7;//待通道二取完数字量之后,重置取通道七的标准电压的数字量delay(1); //第一次需要时间来置位以防万一TR1=1; //此处开启定时器开始定时器控制步长ADC_CONTR|=ADC_START; //此处开启ad转换统一开始时间开始ad 时间很短while(TF1==0); //因为步长大于ad采集时间,所以此处会进入ad中断取!!ADC_RES》bus!!等待定时器控制步长完再把数bus>>zhi[i]TF1=0;//软件查询,需软件清中断申请位TR1=0;//此处关闭为了不让它再计时***定时器计满溢出回零之后(方式0、1、3)会重新开始从零计数所以要先关闭再说****TH1=Gbuchang;TL1=Lbuchang;cankao=bus;//cankao为标准电压的数字量bus=0;//清零}EA=0;flag1=1;zhi3[geshu+2]=geshu;//显示个数zhi3[geshu+4]=256*TH0+TL0;//显示时间,看看取数时间是否超过20000uszhi3[geshu+6]=cankao;//显示标准参考电压数字量cha4=0;//ADC_CONTR&=!ADC_POWER; //ad电源的开断会使内部电压不稳,导致数值不稳//************循环M遍显示取到的N个数值*************************************while(M--){//****处理数据:【zhi[i],zhi1[u],zhi2[v],sum,zhi2】均为小数,zhenzhi,geshu,时间,zhi3[w]为整数//****涉及变量:zhi1[u],zhi2[v],zhi3[w]// u,v,w,sum,zhi2,zhenzhifor(u=0;u<geshu;u++) //只处理geshu以前的数{zhi1[u]=zhi[u]*3/cankao;//此处用(暂选3V)精确电压确定的单个位电压来计算}for(v=0;v<geshu;v++){zhi2[v]=zhi1[v]*zhi1[v];//小数sum+=zhi2[v];//平方和此处bus已经乘了1000,可以说已经取了4位有效数字}junzhi=sum/(geshu);//junzhi为小数值,zhenzhi=sqrt(junzhi)*1000;//zhenzhi为整数值此处已经*1000提取了有效数字zhi3[geshu+8]=zhenzhi;for(w=0;w<geshu;w++)//仅对geshu前的数处理zhi3[w]=zhi1[w]*1000;}//显示程序只显示zhi3[N]的整数值for(j=0;j<N;j++) //循环显示N个数{LedNumVal=zhi3[j];LedOut[0]=Disp_T ab[LedNumVal%100000000/10000000]; //取各个位LedOut[1]=Disp_T ab[LedNumVal%10000000/1000000];LedOut[2]=Disp_T ab[LedNumVal%1000000/100000];LedOut[3]=Disp_T ab[LedNumVal%100000/10000];LedOut[4]=Disp_T ab[LedNumVal%10000/1000]|0x80; //千位LedOut[5]=Disp_T ab[LedNumVal%1000/100]; //百位LedOut[6]=Disp_T ab[LedNumVal%100/10];//十位LedOut[7]=Disp_T ab[LedNumVal%10]; //个位//EA=0; //此处关中断有效的解决了ad打断程序进行的问题去掉它就可以循环了!!for(k=0;k<125;k++) //循环显示这个数300次,为了能看清它大点 cha2就不亮了到了200以上怎么就那么长时间??{cha1=1;for(s=0;s<8;s++) //只显示8个数字{P0=LedOut[s];switch(s) //使用switch 语句控制位选也可以是用查表的方式学员可以试着自己修改{case0:LS138A=0; LS138B=0; LS138C=0; break;case 1:LS138A=1; LS138B=0; LS138C=0; break;case 2:LS138A=0; LS138B=1; LS138C=0; break;case 3:LS138A=1; LS138B=1; LS138C=0; break;case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}delay(5);cha1=0;}cha2=1; //}cha2=0; //每换数一次显示一下}bx++;P0=Disp_Tab[bx]; //显示管显示为“0”delay(2000);//搞清楚此处延时的影响!!}cha3=1;cha4=1;//delay(10000);}}//**********外部中断1控制取数从零点开始flag1和flag3的作用仅仅是控制完整周期(不再开启和关闭中断或定时器)**********// void adc_kai() interrupt 2//外部中断1 中断号2 3^3引脚{// flag1=!flag1;// if(flag1==1)// flag1=0;// else flag1=1;kd++;if(kd==1){flag1=1;}if(kd==2){kd=0;flag1=0;}//**********ad中断程序定时器查询和再置数(控制步长) ad取数**********//void adc_qushu() interrupt 5{ADC_CONTR&=!ADC_FLAG; //每次都要用软件清中断标志位bus=ADC_RES;ADC_RES=0;ADC_CONTR=ADC_POWER|ADC_SPEEDHH|CH2; //?是否需要每次都上电选速度和通道}//**********延时**********//void delay(int q){int z;while(q--){z=100;while(z--);}}。
STC12C5A60S2单片机实现AD采样并液晶显示
STC12C5A60S2单片机实现AD采样并液晶显示STC12C5A60S2是一款高性能、低功耗的8051内核单片机。
以下是一种基于该单片机进行AD采样并液晶显示的实现方案。
请注意,由于字数限制,以下内容是基本的框架和步骤,具体细节还需要根据具体需求进行调整。
1.准备材料和设备:-STC12C5A60S2单片机主控板-16x2液晶显示屏-AD转换器(例如MCP3008)-电压传感器模块-连接线、电阻、电容等2.连接硬件:-将液晶显示屏的VCC、GND和信号线(如RS、R/W、EN、D0-D7等)连接到STC12C5A60S2单片机对应的引脚。
-将AD转换器的VCC、GND和信号线(如CLK、DOUT、DIN、CS等)连接到STC12C5A60S2单片机对应的引脚。
-将电压传感器模块的输出引脚连接到AD转换器的输入引脚。
3.编写代码:-使用C语言编写STC12C5A60S2单片机的代码,包括初始化设置、AD 采样、数据处理和液晶显示等部分。
-在初始化设置中,设置AD转换器的引脚和时钟,配置液晶显示屏的引脚和参数。
-在AD采样部分,通过SPI通信协议与AD转换器进行通信,获取电压传感器模块的输出电压值。
-在数据处理部分,将采样到的原始数据经过相应的处理,如校正、换算等。
-在液晶显示部分,将处理后的数据显示到液晶屏上,并通过适当的界面设计和显示格式展示结果。
4.烧录程序:-使用相应的编程工具将编写好的代码烧录到STC12C5A60S2单片机。
-确保烧录成功,并断开编程工具的连接。
5.调试测试:-连接好硬件后,给电压传感器模块供电,确保电压输入正常。
-上电运行STC12C5A60S2单片机,液晶显示屏应显示出AD采样后的结果。
-对不同的输入电压进行测试,观察液晶屏上的显示结果是否与实际输入电压相符。
请注意,以上仅是基本的框架和步骤,实际应用中还需要根据具体需求和应用场景进行相应的优化和调整。
最新STC12C5A60S2单片机的10位AD转换程序
STC12C5A60S2单片机的10位AD转换程序#include"stc12c5a.h" //头文件在STC公司主页上下载#include"stdio.h" //输入输出函数#include"intrins.h"//------------------------------------------------------------------------------void AD_init(); //初始化ADvoid serial_init();void delay(unsigned int a);float AD_work(unsigned char channel);unsigned int AD_get(unsigned char channel);//------------------------------------------------------------------------------void main() //主程序{AD_init(); //A/D转换初始化serial_init(); //串口初始化while(1){unsigned char i;for(i=0;i<8;i++) //循环发送P1.0-P1.7的转换数值{TI=1; //使用printf函数前须先将发送标志位TI置1printf("The P1.%bd voltage is %f\n",i,AD_work(i));TI=0;delay(1000); //延时约1s}}}//------------------------------------------------------------------------------unsigned int AD_get(unsigned char channel){ADC_CONTR=0x88|channel; //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0_nop_(); _nop_(); _nop_(); _nop_(); //要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器while(!(ADC_CONTR&0x10)); //等待转换完成ADC_CONTR&=0xe7; //关闭AD转换,ADC_FLAG位由软件清0return(ADC_RES*4+ADC_RESL); //返回AD转换完成的10位数据(16进制)}//------------------------------------------------------------------------------float AD_work(unsigned char channel){float AD_val; //定义处理后的数值AD_val为浮点数unsigned char i;for(i=0;i<100;i++)AD_val+=AD_get(channel); //转换100次求平均值(提高精度)AD_val/=100;AD_val=(AD_val*5)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值return AD_val;}//------------------------------------------------------------------------------void delay(unsigned int a) //延时约1ms{unsigned int i;while (--a!=0)for(i=600;i>0;i--); //1T单片机i=600,若是12T单片机i=125}//------------------------------------------------------------------------------void serial_init(){TMOD=0x20;TH1=0xfd;TL1=0xfd; //设置9600波特率SCON=0x50; //串口方式1,允许接收TR1=1;}//------------------------------------------------------------------------------void AD_init(){P1ASF=0xff; //P1口全部作为模拟功能AD使用ADC_RES=0; //清零转换结果寄存器高8位ADC_RESL=0; //清零转换结果寄存器低2位ADC_CONTR=0x80;//开启AD电源delay(2); //等待1ms,让AD电源稳定}/* 酱炒牛柳条:Sautéed Beef Filet in XO Sauce阿香婆石头烤肉:Beef BBQ with Spicy Sauce八宝菠菜:Spinach with Eight Delicacies白菜豆腐焖酥肉:Braised Pork Cubes with Tofu and Chinese Cabbage白菜心拌蜇头:Marinated Jellyfish and Chinese Cabbage in Vinaigrette白灵菇扣鸭掌:Mushrooms with Duck Feet白灵菇牛柳:Stir-Fried Beef Filet with Mushrooms白切鸡:Boiled Chicken with Sauce白灼肥牛:Scalded Beef百叶结烧肉:Stewed Pork Cubes and Tofu Skin in Brown Sauce 板栗红烧肉:Braised Pork with Chestnuts拌八爪鱼:Spicy Cuttlefish拌豆腐丝:Shredded Tofu with Sauce拌海螺:Whelks and Cucumber拌苦菜:Mixed Bitter Vegetables拌茄泥:Mashed Eggplant with Garlic拌双耳:Tossed Black and White Fungus拌爽口海苔:Sea Moss with Sauce拌香椿苗:Chinese Toon with Sauce包子:Baozi鲍鱼红烧肉:Braised Pork with Abalone鲍汁扣东坡肉:Braised Dongpo Pork with Abalone Sauce。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ADC#include<STC12C5A60S2.H>#include<intrins.h>//51基本运算(包括_nop_空函数)#include"ad.h"#include"uart.h"unsigned char code dispcode[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};void AD_Configurate (uchar ChannelNum){uchar AD_FLAG=0; //存储A/D转换标志ChannelNum &= 0x0f; //选择ADC的个接口中的一个(0111 清高位)ADC_CONTR = 0x40; //ADC转换的速度(XX0 0000 其中XX控制速度,请根据数据手册设置)_nop_();ADC_CONTR |= ChannelNum; //选择A/D当前通道_nop_();ADC_CONTR |= 0x80; //启动A/D电源delay(1); //使输入电压达到稳定(ms即可)}unsigned int ReadADV alue (void){unsigned char AD_FLAG=0; //存储A/D转换标志ADC_CONTR |= 0x08; //启动A/D转换(1000 令ADCS = 1)_nop_();_nop_();_nop_();_nop_();while (AD_FLAG ==0)//等待A/D转换结束{AD_FLAG = (ADC_CONTR & 0x10); //0001 0000测试A/D转换结束否}ADC_CONTR &= 0xE7; //1111 0111 清ADC_FLAG位, 关闭A/D转换,return(ADC_RES*4+ADC_RESL);//返回A/D转换结果(位ADC数据高位在ADC_RES中,低位在ADC_RESL中)}void DigitalTube(unsigned long number){P2=0xef; //1110 1111P0=dispcode[number%10]; //显示number的个位delay(7);P2=0xdf; //1101 1111P0=(dispcode[number/10%10]); //显示number的十位delay(7);P2=0xbf; //1011 1111P0=(dispcode[number/100%10]); //显示number的百位delay(7);P2=0x7f; //1011 1111P0=(dispcode[number/1000]); //显示number的千位delay(7);}void delay (unsigned int a ){unsigned int i;while (--a != 0){for (i = 0; i < 600; i++);}}void GPIO_init (void){P2M0 = 0x0F; //0000 1111 //I/O接口的设置P2M1 = 0x00; //0000 0000 //I/O接口的设置P1M1 = 0x01; //P1.0作为ad功能}PWM#include<STC12C5A60S2.H>#include"pwm.h"#include"uart.h"unsigned int xdata FirstData=0; //上升沿捕捉数据unsigned int xdata SeconedData=0; //下降沿捕捉数据高电平时间=SeconedData-FirstData unsigned int xdata HighLevel=0; // 保存被测波形高电平时间对于测方波即使半个周期//采用半个周期的测法主要是提高可被测波形的频率范围unsigned int xdata Frequency=0; // 保存频率的变量bit Capture_over = 0; //捕获完成标志位void pwm_init(void){CMOD=0x80; //0000 0010 PCA工作模式寄存器系统时钟/12 计数器溢出中断CF CCAP0H =(CCAP0L = 254); //PCA捕捉/比较寄存器127 高低点CCAPM0=0x42; //0100 0010// CCAP1H =(CCAP1L = 0x7f);// CCAPM1=0x42;CCAPM1 = 0x21;//16位捕获模式,上升沿触打开捕获中断CCF1CCAP1L = 0x00;CCAP1H = 0x00;EA = 1;CCON=0x40; //0100 0000 PCA控制寄存器CR=1 启动PCA计数器阵列计数}void SetPwm0DutyCycle(unsigned int x) //占空比设置函数{unsigned int h=0,l=0;l=x&0xff;h=x>>8;CCAP0L=l;CCAP0H=h; //设置比较值}void PCA_Interrupt(void) interrupt 7{if (CCF1) //PCA模块中断{CCF1 = 0;if(FirstData == 0) // 上升沿中断{FirstData = CCAP1H; //获得捕捉数据的高位//高位<<8+低位构成位整数FirstData = (FirstData << 8) + CCAP1L;CCAPM1 = 0x11;// 下降沿捕获}else// 下降沿中断{CCF1 = 0; // 清CCF中断标志SeconedData = CCAP1H; //获得捕捉数据的高位//高位<<8+低位构成位整数SeconedData = (SeconedData << 8) + CCAP1L;HighLevel = SeconedData - FirstData; //计数值单位为usFrequency = (long)456000/ HighLevel; // 得到周期CR = 0;//停止PCA计数器计数CCAPM1 = 0x10;//停止捕获中断CCF0产生FirstData=0; // 为下一次捕捉设定初始条件CCAP1L = 0x00;//清零CCAP1H = 0x00;CL = 0x00; //清PCA计数器CH = 0x00;CCAPM1 = 0x21;Capture_over = 1;//捕获完成标志位}}// if(CF == 1) //PCA溢出中断// {// USART_Send_Str(" ;;;;;;;");// CF = 0; //清PCA溢出中断标志// CCAPM1 = 0x21;// FirstData=0; // 为下一次捕捉设定初始条件// CCAP1L = 0x00;//清零// CCAP1H = 0x00;// }}UART#include<STC12C5A60S2.H>#include<stdio.h>#include<string.h>#include"uart.h"//void uartinit(void)//{//// SCON = 0x50; //REN=1允许串行接受状态,串口工作模式// TMOD|= 0x20; //定时器工作方式// PCON|= 0x80;// //TH1 = 0xFD; //baud*2 /* reload value 19200、数据位、停止位。
效验位无(11.0592) // //TH1 = 0xF3; //baud*2 /* 波特率、数据位、停止位。
效验位无(12M)// TH1 = 0xFa;// TL1 = 0xFa;// TR1 = 1;// ES = 1; //开串口中断// EA = 1; // 开总中断//}//void delay1ms(unsigned int delay1ms)//{// unsigned int i,j;// for(;delay1ms>0;delay1ms--)// for(i=0;i<7;i++)// for(j=0;j<210;j++);//}void Uart_Init(void) //使用独立波特率发生器作为波特率发生器{SCON = 0x50; //0101,0000 8位可变波特率,无奇偶校验位BRT = 0xfd;AUXR = 0x11;//0001 0001// T0x12,T1x12,UART_M0x6,BRTR,S2SMOD,BR Tx12,XRAM,S1BRS// Baud = Fosc/(256 - RELOAD_COUNT)/32/12 (12T模式)// Baud = Fosc/(256 - RELOAD_COUNT)/32 (1T模式)// BRTR = 1,启动独立波特率发生器// S1BRS = 1,串口选择独立波特率发生器作为波特率发生器,// 此时定时器可以释放出来作为定时器,计数器,时钟输出使用//AUXR1 = 0x80; //释放该行指令,则串行口从P3口切换到P1口ES = 1; //允许串口中断EA = 1; //开总中断}//void send_UART(unsigned char i)//{// ES = 0; //关串口中断// //TI = 0; //清零串口发送完成中断请求标志// SBUF = i;// while(TI ==0); //等待发送完成// TI = 0; //清零串口发送完成中断请求标志// delay1ms(10);// ES = 1; //允许串口中断//}void UART_Interrupt_Receive(void) interrupt 4{unsigned char k = 0;if(RI==1){RI=0;k=SBUF;USART_Send_Byte(k);}else{TI=0;}}void USART_Send_Byte(unsigned char Data){SBUF=Data;while (!TI);TI=0;}void USART_Send_Enter(void){USART_Send_Byte(0x0d);USART_Send_Byte(0x0a);}void USART_Send_Str(char *Data){unsigned char i;unsigned char len = strlen(Data)-1;for (i=0; i<len; i++){USART_Send_Byte(Data[i]);}if(Data[i]=='\n'){USART_Send_Enter();}else{USART_Send_Byte(Data[i]);}}void numtostr(unsigned int dat,char *str) {char temp[20];unsigned int i=0,j=0;i=0;while(dat){temp[i]=dat%10+0x30;i++;dat/=10;}j=i;for(i=0;i<j;i++){str[i]=temp[j-i-1];}if(!i) {str[i++]='0';}str[i]=0;}void USART_Put_Num(unsigned int dat) {char xdata temp[10];numtostr(dat,temp);USART_Send_Str(temp);}//void uart_delay(unsigned int i)//{// unsigned char j;// for(i; i > 0; i--)// for(j = 200; j > 0; j--) ;////}KEY#include<STC12C5A60S2.H>//#include <intrins.h> //51基本运算(包括_nop_空函数)#include"uart.h"#include"pwm.h"#include"KEY.h"#include"ad.h"unsigned int xdata KeyNumV al=0,Second=0;unsigned int xdata FrequencyBit=1, FrequencyTen=2,FrequencyHundred=3,conter=0; extern unsigned char code dispcode[11];extern unsigned int xdata Frequency;extern unsigned int xdata mode;bit flag=0;void display(void){int j;P2=0xef; //1110 1111if(KeyNumV al==1){if(flag)P0=0xff;elseP0=dispcode[FrequencyBit];}elseP0=dispcode[FrequencyBit]; //显示number的个位delay(7);P2=0xdf; //1101 1111if(KeyNumV al==2){if(flag)P0=0xff;elseP0=dispcode[FrequencyTen];}elseP0=(dispcode[FrequencyTen]); //显示number的十位delay(7);P2=0xbf; //1011 1111if(KeyNumV al==3){if(flag)P0=0xff;elseP0=dispcode[FrequencyHundred];}elseP0=(dispcode[FrequencyHundred]); //显示number的百位delay(7);P2=0x7f; //1011 1111 P0=(dispcode[0]); //显示number的千位delay(7);j++;if(10==j) //延时闪烁时间{j=0;flag=!flag;}if(KeyNumV al==4)Frequency=FrequencyHundred*100+FrequencyTen*10+FrequencyBit; }void key_scan(void){if(KEY3==0){while(!KEY3) //防止掉显{ ;}switch(KeyNumV al){case 1:FrequencyBit++;if(FrequencyBit>9)FrequencyBit=0;break;case 2:FrequencyTen++;if(FrequencyTen>9)FrequencyTen=0;break;case 3:FrequencyHundred++;if(FrequencyHundred>9)FrequencyHundred=0;break;default:break;}}if(KEY4==0){while(!KEY4) //防止掉显{ ;}switch(KeyNumV al){case 1:FrequencyBit--;if(FrequencyBit>9)FrequencyBit=9;break;case 2:FrequencyTen--;if(FrequencyTen>9)FrequencyTen=9;break;case 3:FrequencyHundred--;if(FrequencyHundred>9)FrequencyHundred=9;break;default:break;}}}void exit2(void) interrupt 2{EX1=0; //关外部中断//delay(100);if( mode==1){KeyNumV al++;USART_Put_Num(KeyNumV al);if(KeyNumV al>4)KeyNumV al=0;}EX1=1; //开外部中断}Main#include<STC12C5A60S2.H>//#include <intrins.h> //51基本运算(包括_nop_空函数)#include"uart.h"#include"ad.h"#include"pwm.h"#include"KEY.h"long xdata temp=0,aa,bian=0;unsigned int xdata pwmvalue=0;unsigned int xdata mode=0,LedNumVal_1=0; //计数按键次数extern unsigned int xdata KeyNumV al;unsigned int xdata Dutycycle=0;extern unsigned int xdata HighLevel,Frequency;//保存(高电平)周期的变量=两次捕捉数据之差保存频率的变量extern bit Capture_over ;//捕获完成标志位void main (void){int i;GPIO_init (); //AD与数码管引脚功能配置pwm_init(); //PWM初始化P1.3产生PWM P1.4捕获频率Uart_Init(); //串口初始化AD_Configurate(0);//ad1配置IT0=1; //下降沿触发EX0=1;IT1=1; //下降沿触发EX1=1;EA=1;//USART_Send_Str("ok"); //测试串口while(1){if(mode==0)//模式一{if(KEY3==0){while(!KEY3) //按键消除抖动{ ;}LedNumV al_1++;if(LedNumVal_1>=2)LedNumV al_1=0;}switch(LedNumV al_1) //按键次数{case 0:DigitalTube(temp);aa=0;bian=0;LED=0;break; //显示电压值(mv)case 1:DigitalTube(Frequency);aa=0;bian=0;LED=1;break; //显示频率(HZ)//case 2:DigitalTube(Dutycycle);aa=0;bian=0;LED=0;break;default:break;}for(i=0;i<10;i++) //AD采集10次求平均数{aa = ReadADV alue();bian+=aa;}bian =bian/10; // ReadADV alue();temp =(bian*5030)/1024; //电压转换pwmvalue =65535-(65535*bian)/1023;//255-(255*bian)/1024; //PWM与电压的关系转换SetPwm0DutyCycle(pwmvalue); //设定PWM的占空比pwmvalue// Dutycycle=pwmvalue*100/6553;// else if(pwmvalue==0)// SetPwm0DutyCycle(1);if(Capture_over){CCF1 = 0; // 清CCF中断标志Capture_over = 0;//// USART_Send_Str(" HighLevel=");// USART_Put_Num(HighLevel);// USART_Send_Str(" Frequency=");// USART_Put_Num(Frequency);CCAPM1 = 0x21; //开上升沿捕获CR = 1; //启动PCA计数}}else//mode2{key_scan();display();LED=1;if(Capture_over){CCF1 = 0; // 清CCF中断标志Capture_over = 0;// USART_Send_Str(" HighLevel=");// USART_Put_Num(HighLevel);// USART_Send_Str(" Frequency=");// USART_Put_Num(Frequency);CCAPM1 = 0x21; //开上升沿捕获CR = 1; //启动PCA计数}}}}void exit1(void) interrupt 0{EX0=0; //关外部中断delay(100);mode++;if(mode>=2)mode=0;EX0=1; //开外部中断}。