STC12C5A60S2内部PWM应用
STC12C5A60S2各模块的应用分享大家
STC12C5A60S2各模块的应用分享大家/*****************串口应用******************/ ///////////////////串口一//////////////#include"12c5a60s2.h"#include"uart.h"unsignedcharbuf[3],g;voidinitUart(){EA=1;BRT=0XFD;//独立波特率发生器9600AUXR=0X11;//启动独立波特率发生器,12分频// TMOD=0X20;//用定时器1做波特率发生器//TH1=0XFD;//TL1=0XFD;//TR1=1;REN=1;SM1=1;ES=1;g=0;}voidsendDate(unsigned char date){SBUF=date;while(!TI);TI=0;}void work(){sendDate(buf[0]); sendDate(buf[1]);}voidres()interrupt 4{buf[g++]=SBUF;if(g>;=2){g=0;work();}while(!RI);RI=0;}////////////////////串口二//////////////// #include;#include"uart2.h"#defineS2TI 0X02//不能位寻址#defineS2RI 0X01//不能位寻址unsigned charshuzhi;voidinitUART2(){BRT=0XFD;//定初值9600AUXR=0X11;//使用波特率独立发生器 12分频 9600 //AUXR=0X19;//使用波特率独立发生器 1分频 19200 EA=1;IE2=0X01;//ES2=1;S2CON=0X50;//S2REN=1;S2SM1=1;}voidsenddate(unsigned char date){S2BUF=date;//判断是否是一if(S2CON&S2TI)//清零S2CON&=~S2TI;}void uart2r()interrupt 8{if(S2CON&S2RI)//判断是否是一{S2CON&=~S2RI;//清零shuzhi=S2BUF;senddate(0x40);}}/******************AD转换*************************/#include"12c5a60s2.h"#include"12c5aad.h"#include;//寄存器地址声明,有12c5a60s2 头文件可省略//sfr ADC_CONTR =0XBC;//sfr ADC_RES =0XBD;//sfr ADC_ERSL =0XBE;//sfr P1ASF =0X9D;//宏定义#define ADC_POWER 0X80// ad电源控制位#define ADC_FLAG0x10//ad转换结束标志位#define ADC_START0x08//ad转换开始控制位#define ADC_SPEEDLL 0x00 //540 转换速率#define ADC_SPEEDL 0x20 //360 转换速率#define ADC_SPEEDH 0x40 //180 转换速率#define ADC_SPEEDHH 0x60 //90 转换速率//ad转换延时函数voiddelayad(unsignedint z){unsignedintx,y;for(x=5000;x>;0;x--)for(y=z;y>;0;y--);}//ad初始化函数voidinitad(){P1ASF=0XFF;//设置P1口为ad转换模式ADC_RES=0;//ad转换结果寄存器清零ADC_CONTR=ADC_POWER|ADC_SPEEDLL; //打开ad转换电源,最慢频率delayad(2);//延时待电源稳定提高精确性}unsignedchar getAD(unsigned char ch) //ch通道选择{ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|ch ; _nop_(); _nop_();_nop_();_nop_();while(!(ADC_CONTR&ADC_FLAG));//ad转换完成 FALG 为1ADC_CONTR&=~ADC_FLAG;//FALG置置零return ADC_RES;}/********************PCA/PWM*****************/ /////////////////////中断模式/////////////////////#include;#include"pcaint.h"unsigned charmiao;voidinitPCAint(void){CCON=0;CL=0;CH=0;CMOD=0X00;//禁止CF中断CCAPM0=0X11;// (CAPN0 负捕获,CAPP0 正捕获)本模块负捕获CCAPM1=0X21; // 模块一正捕获CR=1;//开计数列阵EA=1;//开总中断}voidpca()interrupt7{if(CCF0==1){CCF0=0;//清零模块中断标志位miao++;}if(CCF1==1){CCF1=0;//清零模块中断标志位miao--;}}//////////////////////////定时器模式////////////////////#include;#include"pcatime.h" unsignedint value;//数组赋值unsigned char ptime;//ptime=0xb402;50ms定时 0x2400 10ms voidinitPCATime(){CCON=0X00;//标志位清零CL=0;//pca L列阵清零CH=0;//PCA H列阵清零CMOD=0X00;//选择时钟模式CCAP1L=value;//先赋值高位CCAP1H=value>;>;8; //赋值CCAPM1=0X49;//允许比较器ECOM1,MAT1、ECCF1置位允许CCF1中断CR=1;//允许列阵EA=1;//开总中断}voidpcatime()interrupt 7//两个PCA模块都是中断7 {unsignedint i;CL=0;//清零不然是溢出时钟,定时无效 CH=0;//清零不然是溢出时钟,定时无效 CCF1=0;CCAP1L=value;CCAP1H=value>;>;8;i++;if(i>;=20){i=0;ptime++;}}///////////////////////PWM模式//////////////////////#include"12c5a60s2.h" #include"12c5apwm.h" voidinitPWM(void ){CCON=0;//关闭PCA计数及标志位清零CL=0;// 清空pca计数低位CH=0;// 清空pca计数高位CMOD=0X08;// 用系统时钟不分频//CCAP0H=CCAP0L=0x01;// 模块0复初值CCAPM0=0X42;//允许模块0比较器工作,脉宽调制模式//CCAP1H=CCAP1L=0X01;//模块1复初值CCAPM1=0X42;//允许模块1比较器工作,脉宽调制模式CR=1;//启动pca计数}void tiaoj(unsignedchar pwmH,unsigned char pwmL){CCAP0H=CCAP0L=pwmH;// 模块0复值CCAP1H=CCAP1L=pwmL;// 模块1复值}/**********************EEPROM******************** *****/#include;#include;#include"eeporm.h"#defineRdeeprom 0x01#defineWreeprom 0x02#defineERSeeprom 0x03#defineWTime0x01 // 0x02 0x03 0x00sfr ISP_DATA=0Xc2;sfr ISP_ADDRH=0Xc3;sfr ISP_ADDRL=0Xc4;sfr ISP_CMD=0Xc5;sfr ISP_TRIG=0Xc6;sfr ISP_CONTR=0Xc7;unsigned char miao,miao2,miao3;bit int0flag;void ISP_Open(void){EA=0;//关中断ISP_CONTR=ISP_CONTR&0X18;//清零ISP_CONTR=ISP_CONTR|WTime;//等待时间ISP_CONTR=ISP_CONTR|0x80;//使能ISP}void ISP_Close(void){ISP_CONTR=ISP_CONTR&0X7F; //停止ISP使能ISP_TRIG=0X00;//命令触发寄存器清零EA=1;//开中断}void ISP_Goon(void){//打开ISPISP_Open();ISP_TRIG=0x5a;//写触发命令ISP_TRIG=0xa5;//写触发命令_nop_();//等待}voidbyte_write(unsigned int add,unsigned char dat) //写某地址数据{ISP_ADDRH=(unsignedchar)(add>;>;8);//地址高位ISP_ADDRL=(unsignedchar)(add&0x00ff);//地址低位ISP_CMD=ISP_CMD&0XF8;//命令模式复位ISP_CMD=ISP_CMD|Wreeprom;//写命令ISP_DATA=dat;//读写寄存器赋值ISP_Goon();//打开、触发ISP_Close();_nop_();//关闭}voidsector(unsigned int add) {ISP_ADDRH=(unsignedchar)(add>;>;8);//地址高位ISP_ADDRL=0x00;//地址低位ISP_CMD=ISP_CMD&0XF8;//命令模式复位ISP_CMD=ISP_CMD|ERSeeprom;//删命令ISP_Goon();//打开、触发ISP_Close();_nop_();}unsignedchar byte_read(unsigned int add) {ISP_ADDRH=(unsignedchar)(add>;>;8);//地址高位ISP_ADDRL=(unsignedchar)(add&0x00ff);//地址低位ISP_CMD=ISP_CMD&0XF8;//命令模式复位ISP_CMD=ISP_CMD|Rdeeprom;//读命令ISP_Goon();//打开、触发ISP_Close();_nop_();return (ISP_DATA);}voidinitc(){IT0=1;EX0=1;EA=1;}voidint0()interrupt 0{if(int0flag==1){EA=0;sector(0x00ff); //0000h-03ffh byte_write(0X00ff,miao3);EA=1;}}///////////////////////////////////////////////// ////////写的一般,不足之处还望包涵,均测试通过,欢迎提好的建议。
STC12C5A60S2内部PWM应用
【PWM ] CLKOUT2/ADCO/P1.01_ ADC1/PL1 匚 RXD2ZECI/ADC2/P12 匚 TxD2/CPP0/ADC3/P13 U SS/CPP1/ADC4/P1.4 I ------- MOSI/ADC5/PL5 CZ MISO/ADC6/PL6 U SCLK/ADC7/P1.7C ______ P4.7/RST U INT/RXD/P3.0 匚 _TxD/P3J^ 而&P3 2匚 __^Tl/P33rZ CLKOUTO/INT/TO/P3.4 匚 CLKOUTl/TNTm/P3^ 匚 WR/P3.6CZ RD/P3.7 匚 XTAL2CZ XTAL1匚 Gnd I — 0123456789wl-OJ *1->-.*1-* ■n -)P D WL PSTQ2C5A6QSPM莒7 4r 口0 9 8 7 65 4 3 2 10 433333 33 3338765432 1 2 2 2 2 2 2 2 Vcc POO POJ P0.2 P0.3 P0.4 P0.5 P0.6 P0.7EX LVD/P4.6/RST2 ALE/P4.5 NA/P4.4 P27/A15 P2.6/A14 P2.5/A13 P2.4/A12 P23/A11 P2.2/A10 P2J/A9 P2.0/A810.8利用P 、VM 实现D/A 功能的典型应用线路图P2.2P23TxDK.]PO.O JCIAL2XIALlDJTGP3.2PQI INTI P3.3CLKOUTOZECI'T&Pa.-l CLKDUn-PlMJdl.Tl P3J4..5WP2K S=========S C7320 12 3 4-5621 O 9 8 7 5 5 4 31 _o 9 8 73-33 2 2 2s s2 2VDD P2.1 P2.0 P1.7-ADC7 Pl 6 ADC6 PI 5 ADC5 P03 P1.4-!ADC4 PlA-'ADCa PQ2PUADC2ZVD P1.1-ADC1 PLO-'ADCGP3.7WM0 — P2_7P2 (6)第10章STC12C5A60S2系列单片机PCA/PWM 应用STC12C5A60S2系列单片机集成了两路可编程计数器阵列(PCA)模块,可用于软件定时器、 外部腕冲的捕捉、高一速输出以及脉宽调制(PWM)输出,1. PCA工作模式寄存器C3IODPCA工作模式寄存器的格式如下;CIDL:空闲模式下屉否停jLPCAit数的控制位。
(完整word版)STC12C5A60S2ADPWM应用例程
#include”stc12c5a.h" //头文件在STC公司主页上下载#include"stdio.h"#include”intrins。
h”#define uchar unsigned char//—-—————---—————-----———————-—-——-————---—-—————————--————-————--—-—---—-—-—---void AD_init();//AD初始化函数void delay(unsigned int a); //延时函数float AD_work(unsigned char channel); //AD数值处理函数unsigned int AD_get(unsigned char channel);//AD转换函数unsigned char sh1,ge1,n1,m1,aa;int num,pwm,V,temp1;sbit PWM=P0^0; //定义PWM输出口为P0^0sbit key1=P0^1;sbit key2=P0^2;//--—---—----—----——---—-—-—————---—----——--———---———-———-———-—-—--————--—-——-—-void send(uchar data1){ES=0; //关闭中断TI=0;SBUF=data1;while(!TI); //等待发送完成TI=0;//中断标志位清0ES=1;//打开中断}void display() //串口发送AD{temp1=V;sh1=temp1/1000;ge1=(temp1%1000)/100;n1=((temp1%1000)%100)/10;send(sh1+48);send(’.');send(ge1+48);send(n1+48);send(’V');send(' ');}//--——-——-----—--—--———------———--————-—-——-—-——----———-—-—--—-—-———--—-—-——---—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){double AD_val,AD_vale; //定义处理后的数值AD_val为浮点数unsigned char i;for(i=0;i<100;i++)AD_val+=AD_get(channel); //转换100次求平均值(提高精度)AD_val/=100;AD_vale=(AD_val*5000)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值V=AD_vale;return V;}//--—-—----——--—------—--—-—---—----—----———-—--—---—————-———---—--—————---—————void delay(unsigned int a)//延时约1ms{unsigned int i;while (-—a!=0)for(i=600;i>0;i-—);}//-—--——-—----——--——--————-——-—-—-—--—--——-————---—-—----—-—--——-—----———-—-——-—//------—-———-——-—--—--——---————-————-—-——-—--—————-—-—--——-—————-—--———--——----void AD_init(){P1ASF=0xff;//P1口全部作为模拟功能AD使用ADC_RES=0;//清零转换结果寄存器高8位ADC_RESL=0;//清零转换结果寄存器低2位ADC_CONTR=0x80;//开启AD电源delay(2);//等待1ms,让AD电源稳定}void anjian(){if(pwm!=100) //加到100不继续加{if(key1==0){delay(10);if(key1==0){pwm++;aa=1;while(!key1);}}}if(pwm!=0) //减到0不继续减{if(key2==0){delay(10);if(key2==0){aa=1;pwm-—;while(!key2);}}}}void main(){AD_init(); //AD初始化TMOD=0x21;TH1=0xfd;TL1=0xfd; //设置9600波特率SCON=0x50; //串口方式1,允许接收TH0=(65536—7)/256; //装初值,设定PWM频率TL0=(65536—7)%256;ET0=1;TR0=1;TR1=1;SM0=0;SM1=1;REN=1;ES=1;EA=1;pwm=50;//占空比为50%while(1){unsigned char i;i=0;//发送P1^i的转换数值(P10口)AD_work(i); //读取AD电压display();if(V〉=3000){aa=0;pwm=0;//占空比为0}if(V〈3000){if(aa==0)pwm=50;anjian();}}}void T0_time()interrupt 1 //中断时间为0.01ms,因PWM输出口输出高低电平共100次为1个周期,所以PWM的周期为1ms,频率为1KHZ{TH0=(65536—7)/256;TL0=(65536-7)%256;num++;if(num〈=pwm)PWM=1;elsePWM=0;if(num==100)num=0;}。
STC12C5A60S2的ADC PWM功能
STC12C5A60S2的ADC+PWM功能STC12C5A60S2单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度可达到250 KHz(25万次/秒)。
脉宽调制(PWM)是一种使用程序来控制波形占空比、周期、相位波形的技术。
STC12C5A60S2单片机的PAC模块可以通过程序设定,使其工作于8位PWM模式。
下面是一段将ADC和PWM结合起来应用的程序:/************************************************ ***************时间:2012.12.1晶振:12MHz功能描述:AD采集电位器的电压信号,然后信号以PWM 信号输出控制LED的亮度(调节电位器)当电位器两端的电压大时,LED较亮,同时用1602显示采集的电压值AD采集通道:P1.0PWM输出: P1.3************************************************* **************/#include;#include;unsigned int result,ge,shifen,baifen;unsigned charseg[10]={'0','1','2','3','4','5','6','7','8','9'} ;//要显示字符sbit RS = P2^4; //命令数据sbit RW = P2^5; //写还是读sbit EN = P2^6; //使能端#define RS_CLR RS=0#define RS_SET RS=1#define RW_CLR RW=0#define RW_SET RW=1#define EN_CLR EN=0#define EN_SET EN=1#define DataPort P0/*------------------------------------------------uS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时长度如下 T=tx2+5 uS------------------------------------------------* /void DelayUs2x(unsigned char t){while(--t);}/*------------------------------------------------mS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编------------------------------------------------* /void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}/*------------------------------------------------判忙函数------------------------------------------------* /bit LCD_Check_Busy(void){DataPort= 0xFF;RS_CLR;RW_SET;EN_CLR;_nop_();EN_SET;return (bit)(DataPort & 0x80);}/*------------------------------------------------写入命令函数------------------------------------------------*/void LCD_Write_Com(unsigned char com){while(LCD_Check_Busy()); //忙则等待RS_CLR;RW_CLR;EN_SET;DataPort= com;_nop_();EN_CLR;}/*------------------------------------------------写入数据函数------------------------------------------------* /void LCD_Write_Data(unsigned char Data){while(LCD_Check_Busy()); //忙则等待RS_SET;RW_CLR;EN_SET;DataPort= Data;_nop_();EN_CLR;}/*------------------------------------------------清屏函数------------------------------------------------* /void LCD_Clear(void){LCD_Write_Com(0x01);DelayMs(5);}/*------------------------------------------------写入字符串函数------------------------------------------------* /void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s){{LCD_Write_Com(0x80 + x); //表示第一行}else{LCD_Write_Com(0xC0 + x); //表示第二行}while (*s){LCD_Write_Data( *s);s ++;}}/*------------------------------------------------写入字符函数------------------------------------------------* /void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data){{LCD_Write_Com(0x80 + x);}else{LCD_Write_Com(0xC0 + x);}LCD_Write_Data( Data);}/*------------------------------------------------LCD初始化函数------------------------------------------------* /void LCD_Init(void){LCD_Write_Com(0x38); /*显示模式设置*/DelayMs(5);LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);LCD_Write_Com(0x08); /*显示关闭*/LCD_Write_Com(0x01); /*显示清屏*/LCD_Write_Com(0x06); /*显示光标移动设置*/ DelayMs(5);LCD_Write_Com(0x0C); /*显示开及光标设置*/ }/*------------------------------------------------ADC初始化函数------------------------------------------------* /void InitADC(){P1ASF =0x01;//使能P1口ADC功能ADC_RES = 0;ADC_CONTR = 0xc8;}/*------------------------------------------------主函数------------------------------------------------* /void main(void){LCD_Init();LCD_Clear();//清屏LCD_Write_String(5,0,"526lab");//(列,行,数据)LCD_Write_String(2,1,"Result:"); InitADC();IE=0xa0;//开中断while (1){//PWM初始化CCON=0;CMOD=0;//1MCCAP0H=CCAP0L=ADC_RES;CCAPM0=0x42;//开启PWMCR=1;//计时开始//调用显示LCD_Write_Char(9,1,seg[ge]);LCD_Write_Char(10,1,'.');LCD_Write_Char(11,1,seg[shifen]);LCD_Write_Char(12,1,seg[baifen]);LCD_Write_Char(13,1,'V');}}/*------------------------------------------------ADC中断处理函数------------------------------------------------* /void adc_isr() interrupt 5 using 1{unsigned int temp;temp=ADC_RES;result=temp*0.01953125*1000;ge=result/1000;shifen=result%1000/100;baifen=result%100/10;ADC_CONTR = 0xc8;//开启转换}12C5A60S2.h的头文件//--------------------------------------------------------------------------------//新一代 1T 8051系列单片机内核特殊功能寄存器 C51 Core SFRs// 7 6 5 4 3 2 1 0Reset 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 Byte0000,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 0Reset Valuesfr AUXR = 0x8E; //Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS0000,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 系列单片机器件手册 说明书
Tel: 0755-********Fax: 0755-********创始人/研发总监:姚永平(139********)宏晶STC 官方网站: 1STC12C5A60S2系列 1T 8051 单片机中文指南全球最大的8051单片机设计公司S T C M C U L i m i t e d .临时技术支持:139********授权代理:南通国芯微电子有限公司总机:0513-5501 2928 / 2929 / 2966传真:0513-5501 2969 / 2956 / 2947宏晶STC 单片机官方网站: Update date: 2011/3/19---高速,高可靠---低功耗,超低价---超���超���� ---�抗静电,�抗干扰---1个时钟/机器周期8051STC12C5A60S2系列单片机器件手册STC12C5A08S2, STC12C5A08ADSTC12C5A16S2, STC12C5A16ADSTC12C5A20S2, STC12C5A20ADSTC12C5A32S2, STC12C5A32ADSTC12C5A40S2, STC12C5A40ADSTC12C5A48S2, STC12C5A48ADSTC12C5A52S2, STC12C5A52ADSTC12C5A56S2, STC12C5A56ADSTC12C5A60S2, STC12C5A60AD STC12C5A62S2, STC12C5A62AD全部中国大陆本土独立自主知识产权,技术处于全球领先水平,请全体中国人民支持,您的支持是中国大陆本土企业统一全球市场的有力保证.目录第1章STC12C5A60S2系列单片机总体介绍 (8)1.1 STC12C5A60S2系列单片机简介 (8)1.2 STC12C5A60S2系列单片机的内部结构 (10)1.3 STC12C5A60S2系列单片机管脚图 (11)1.4 STC12C5A60S2系列单片机选型一览表 (13)1.5 STC12C5A60S2系列单片机最小应用系统 (15)1.6 STC12C5A60S2系列在系统可编程(ISP)典型应用线路图 (17)1.7 STC12C5A60S2系列管脚说明 (19)1.8 STC12C5A60S2系列单片机封装尺寸图 (22)1.9 STC12C5A60S2系列单片机命名规则 (27)1.10 每个单片机具有全球唯一身份证号码(ID号) (28)1.11 如何从传统8051单片机过渡到STC12C5A60S2系列单片机 (31)第2章时钟,省电模式及复位 (35)2.1 STC12C5A60S2系列单片机的时钟 (35)2.1.1 STC12C5A60S2系列单片机内部/外部工作时钟可选 (35)2.1.2 时钟分频及分频寄存器 (36)2.1.3 如何知道单片机内部R/C振荡频率(内部时钟频率) (37)2.1.4 可编程时钟输出 (40)2.2 STC12C5A60S2系列单片机的省电模式 (45)2.2.1 低速模式 (47)2.2.2 空闲模式 (48)2.2.3 掉电模式/停机模式 (48)2.3 复位 (54)2.3.1 外部RST引脚复位(第一复位功能脚) (54)2.3.2 外部低压检测复位(高可靠复位,新增第二复位功能脚RST2复位) (54)2.3.3 外部低压检测若不作第二复位功能时,可作外部低压检测中断 (56)2.3.4 软件复位 (60)2.3.5 上电复位/掉电复位 (60)2.3.6 MAX810专用复位电路 (61)2.3.7 看门狗(WDT)复位 (61)2.3.8 冷启动复位和热启动复位 (65)第3章片内存储器和特殊功能寄存器(SFRs) (66)3.1 程序存储器 (66)3.2 数据存储器(SRAM) (67)3.2.1 内部RAM (67)3.2.2 内部扩展RAM (69)3.2.3 外部扩展的64KB数据存储器(片外RAM) (77)3.3 特殊功能寄存器(SFRs) (80)第4章.STC12C5A60S2系列单片机的I/O口结构 (87)4.1 I/O口各种不同的工作模式及配置介绍 (87)4.2 STC12C5A60S2系列单片机P4/P5口的使用 (92)4.3 I/O口各种不同的工作模式结构框图 (94)4.3.1 准双向口输出配置 (94)4.3.2 强推挽输出配置 (95)4.3.3 仅为输入(高阻)配置 (95)4.3.4 开漏输出配置(若外�上拉电阻,也可读) (95)4.4 一种典型三极管控制电路 (97)4.5 典型发光二极管控制电路 (97)4.6 混合电压供电系统3V/5V器件I/O口互连 (97)4.7 如何让I/O口上电复位时为低电平 (98)4.8 PWM输出时I/O口的状态 (99)4.9 I/O口直接驱动LED数码管应用线路图 (100)4.10 I/O口直接驱动LCD应用线路图 (101)4.11 A/D做按键扫描应用线路图 (102)第5章.指令系统 (103)5.1 寻址方式 (103)5.1.1 立即寻址 (103)5.1.2 直接寻址 (103)5.1.3 间接寻址 (103)5.1.4 寄存器寻址 (104)5.1.5 相对寻址 (104)5.1.6 变址寻址 (104)5.1.7 位寻址 (104)5.2 指令系统分类总结 (105)5.3 传统8051单片机的指令定义 (110)第6章.中断系统 (147)6.1 中断结构 (149)6.2 中断寄存器 (151)6.3 中断优先级 (159)6.4 中断处理 (160)6.5 外部中断 (161)6.6 中断测试程序(C程序及汇编程序) (162)6.6.1 外部中断0(INT0)的测试程序(C程序及汇编程序) (162)6.6.2 外部中断1(INT1)的测试程序(C程序及汇编程序) (166)6.6.3 P3.4/T0/INT下降沿中断(可用于唤醒掉电模式)的测试程序 (170)6.6.4 P3.5/T1/INT下降沿中断(可用于唤醒掉电模式)的测试程序 (172)6.6.5 P3.0/RxD/INT下降沿中断(可用于唤醒掉电模式)的测试程序 (174)—— C程序及汇编程序 (174)6.6.6 低压检测LVD中断(可用于唤醒掉电模式)的测试程序 (177)6.6.7 PCA模块中断(可用于唤醒掉电模式)的测试程序 (180)第7章.定时器/计数器 (184)7.1 定时器/计数器的相关寄存器 (184)7.2 定时器/计数器0工作模式(与传统8051单片机兼容) (189)7.2.1 模式0(13位定时器/计数器) (189)7.2.2 模式1(16位定时器/计数器)及测试程序 (190)7.2.3 模式2(8位自动重装模式) (194)7.2.4 模式3(两个8位计数器) (197)7.3 定时器/计数器1工作模式(与传统8051单片机兼容) (198)7.3.1 模式0(13位定时器/计数器) (198)7.3.2 模式1(16位定时器/计数器) (199)7.3.3 模式2(8位自动重装模式) (203)7.4 可编程时钟输出及测试程序(C程序和汇编程序) (206)7.4.1 定时器0的可编程时钟输出的测试程序 (209)7.4.2 定时器1的可编程时钟输出的测试程序 (211)7.4.3 独立波特率发生器的可编程时钟输出的测试程序 (213)7.5 古老Intel 8051单片机定时器0/1的应用举例 (215)7.6 如何将定时器T0/T1的速度提高12倍 (222)第8章.串行口通信 (223)8.1 串行口1的相关寄存器 (223)8.2 串行口1工作模式 (229)8.2.1 串行口1工作模式0:同步移位寄存器 (229)8.2.2 串行口1工作模式1:8位UART,波特率可变 (231)8.2.3 串行口1工作模式2:9位UART,波特率固定 (233)8.2.4 串行口1工作模式3:9位UART,波特率可变 (235)8.3 串行通信中波特率的设置 (237)8.4 串行口1的测试程序 (242)8.5 串行口2的相关寄存器 (248)8.6 串行口2工作模式 (254)8.7 串行口2的测试程序 (256)8.8 双机通信 (262)8.9 多机通信 (273)第9章.STC12C5A60S2系列单片机的A/D转换器 (279)9.1 A/D转换器的结构 (279)9.2 与A/D转换相关的寄存器 (281)9.3 A/D转换典型应用线路 (286)9.4 A/D做按键扫描应用线路图 (287)9.5 A/D转换模块的参考电压源 (288)9.6 A/D转换测试程序(C程序和汇编程序) (289)9.6.1 A/D转换测试程序(ADC中断方式) (289)9.6.2 A/D转换测试程序(ADC查询方式) (295)第10章.STC12C5A60S2系列单片机PCA/PWM应用 (301)10.1 与PCA/PWM应用有关的特殊功能寄存器 (301)10.2 PCA/PWM模块的结构 (307)10.3 PCA模块的工作模式 (309)10.3.1 捕获模式 (309)10.3.2 16位软件定时器模式 (310)10.3.3 高速输出模式 (311)10.3.4 脉宽调节模式(PWM) (312)10.4 用PCA功能扩展外部中断的示例程序(C程序和汇编程序) (314)10.5 用PCA功能实现定时器的示例程序(C程序和汇编程序) (318)10.6 PCA输出高速脉冲的示例程序(C程序和汇编程序) (322)10.7 PCA输出PWM的示例程序(C程序和汇编程序) (326)10.8 利用PWM实现D/A功能的典型应用线路图 (330)第11章.同步串行外围接口(SPI接口) (331)11.1 与SPI功能模块相关的特殊功能寄存器 (331)11.2 SPI接口的结构 (334)11.3 SPI接口的数据通信 (335)11.3.1 SPI接口的数据通信方式 (336)11.3.2 对SPI进行配置 (338)11.3.3 作为主机/从机时的额外注意事项 (339)11.3.4 通过SS改变模式 (340)11.3.5 写冲突 (340)11.3.6 数据模式 (341)11.4 适用单主单从系统的SPI功能测试程序 (343)11.4.1 中断方式 (343)11.4.2 查询方式 (349)11.5 适用互为主从系统的SPI功能测试程序 (355)11.5.1 中断方式 (355)11.5.2 查询方式 (361)第12章.STC12C5A60S2系列单片机EEPROM的应用 (367)12.1 IAP及EEPROM新增特殊功能寄存器介绍 (367)12.2 STC12C5A60S2系列单片机EEPROM空间大小及地址 (371)12.3 IAP及EEPROM汇编简介 (373)12.4 EEPROM测试程序 (377)第13章.STC12系列单片机开发/编程工具说明 (385)13.1 在系统可编程(ISP)原理,官方演示工具使用说明 (385)13.1.1 在系统可编程(ISP)原理使用说明 (385)13.1.2 STC12C5A60S2系列在系统可编程(ISP)典型应用线路图 (386)13.1.3 电脑端的ISP控制软件界面使用说明 (388)13.1.4 宏晶科技的ISP下载编程工具硬件使用说明 (390)13.1.5 若无RS-232转换器,如何用宏晶的ISP下载板做RS-232通信转换 (391)13.2 编译器/汇编器,编程器,仿真器 (392)13.3 自定义下载演示程序(实现不停电下载) (394)7STC12C5A60S2系列 1T 8051 单片机中文指南全球最大的8051单片机设计公司S T C M C U L i m i t e d .临时技术支持:139********授权代理:南通国芯微电子有限公司总机:0513-5501 2928 / 2929 / 2966传真:0513-5501 2969 / 2956 / 2947附录A :汇编语言编程...................................398附录B :C 语言编程......................................420附录C :STC12C5A60S2系列单片机电气特性...............430附录D :内部常规256字节RAM 间接寻址测试程序...........432附录E :用串口扩展I/O 接口..............................434附录F :利用STC 单片机普通I/O 驱动LCD 显示..............437附录G :一个I/O 口驱动发光二极管并扫描按键..............444附录H :如何利用Keil C 软件减少代码长度.................445附录I :STC12系列单片机取代传统8051注意事项............446附录J :如何采购和授权分销机构.........................450J.1 如何采购 ................................................450J.2 授权分销机构 ............................................451附录K :每日更新内容的备忘录...........................453附录L :以下是各系列的选型指南. (454)L.1 STC15F828EACS 系列选型指南(2011年5月开始送样) ..........454L.2 STC15F204EA 系列选型指南 ...............................454L.3 STC12C5A60S2系列选型指南 ..............................454L.4 STC11/10xx 系列选型指南 .................................454L.5 STC12C5201AD 系列选型指南 ..............................454L.6 STC12C5620AD 系列选型指南 ..............................454L.7 STC12C5410AD 系列选型指南 ..............................454L.8 STC12C2052AD 系列选型指南 ..............................454L.9 STC89C51/STC90C51系列选型指南 . (454)8STC12C5A60S2系列 1T 8051 单片机中文指南全球最大的8051单片机设计公司临时技术支持:139********S T C M C U L i mi t e d .授权代理:南通国芯微电子有限公司总机:0513-5501 2928 / 2929 / 2966传真:0513-5501 2969 / 2956 / 2947第1章 STC12C5A60S2系列单片机总体介绍1.1.STC12C5A60S2系列单片机简介STC12C5A60S2/AD/PWM 系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超�抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12 倍。
12C5A60S2水温控制程序
Abstract: Along with the computer measurement and control technology of the rapid development and wide application, based on singlechip temperature gathering and control system development and application greatly improve the production of temperature in life level of control. This design STC12C5A60S2describes a kind of mainly by MCU control unit, for temperature sensor DS18B20 temperature control system. The control system can real-time storage temperature data and record related to the current time. System design related hardware circuit and related applications. STC12C5A60S2 microcontroller hardware circuit include temperature detection circuit smallest system, and real-time clock circuit, LCD display circuit, communication module circuit, etc. System programming mainly include main program, read temperature subroutine, the calculation of temperature subroutines, key processing procedures, LCD display procedures and data storage procedures, etc.
基于STC12C5A60S2的点光源自适应控制系统
基于STC12C5A60S2的点光源自适应控制系统随着现代科技的发展,点光源自适应控制系统已经成为了目前LED照明产业中的热门技术之一。
其中,STC12C5A60S2单片机则是许多点光源自适应控制系统的核心控制器。
本文将讲述基于STC12C5A60S2单片机的点光源自适应控制系统的设计原理和应用。
1.系统设计原理点光源自适应控制系统是通过对于LED光源的光强度进行控制,从而实现整个照明系统的节能和舒适的照明环境。
该系统的核心就是对光强度的控制单元,在这里,我们选择了STC12C5A60S2单片机作为核心控制器。
STC12C5A60S2单片机有一个强大的、高速的8位CPU,具有40MHz的主频以及8KB的RAM和60KB的Flash存储器。
这样的存储空间足以支持本系统中的数据存储、算法计算以及程序运行。
同时,STC12C5A60S2还有16个外部中断、8个定时器以及两个串口,能够方便地实现与其他外设的连接。
在点光源自适应控制系统中,我们需要采用光敏电阻传感器来感知周围环境的光照强度,并将感知到的数据通过AD转换器传输给STC12C5A60S2单片机。
此时STC12C5A60S2单片机将通过对AD转换器的采样和数据处理,得到一个最佳的光照强度控制值。
在该系统的实际应用中,我们必须考虑所控制的灯光的数量以及灯光的位置等因素。
我们可以通过将STC12C5A60S2单片机与相应的驱动芯片或继电器等电子元件相连,来实现对灯光的整个控制。
2.系统应用在实际应用中,点光源自适应控制系统可以广泛应用于各种室内和室外照明系统中。
例如,在办公室、学校、医院等场所,我们可以根据不同时间段和使用场所,来自动控制灯的亮度,从而实现节能和环保。
另外,在公共场所,如街道、广场和停车场等,我们可以通过该系统自动控制路灯的亮度,提高夜间照明的效果,从而提高路人和车辆的安全性。
3.总结综合来看,点光源自适应控制系统是一种十分实用的技术,能够帮助人们实现节能和环保。
STC12C5A60S2单片机PWM应用
1.PCA工作模式寄存器CMODPCA工作模式寄存器的格式如下:CMOD:PCA工作模式寄存器CIDL:空闲模式下是否停止PCA计数的控制位当CIDL=0时,空闲模式下PCA计数器继续工作;当CIDL=1时,空闲模式下PCA计数器停止工作;CPS2、CPS1、CPS0:PCA计数脉冲源选择控制位。
PCA计数脉冲选择如下表所示:例如,CPS2/CPS1/CPS0=1/0/0时,PCA/PWM的时钟源是SYSclk,不是定时器0,PWM 的频率为SYSclk/265如果要用系统时钟/3来作为PCA的时钟源,应让T0工作在1T模式,计数3个脉冲即产生溢出。
如果此时使用内部RC作为系统时钟(室温情况下,5V单片机为11MHZ~15.5MHZ),可以输出14K~19K频率的PWM。
用T0的溢出可对系统时钟进行1~256级分频。
ECF:PCA计数溢出中断使能位。
当ECF=0时,禁止寄存器CCON中CF位的中断;当ECF=1时,允许寄存器CCON中CF位的中断。
2. 2. PCA控制寄存器CCONPCA控制寄存器的格式如下:CCON:PAC控制寄存器CF:PCA计数阵列溢出标志位。
当PCA计数器溢出时,CF由硬件位置。
如果CMOD 寄存器的ECF位置位,则CF标志可用来产生中断。
CF位可通过硬件或软件置位,但通过软件清零。
CR:PCA计数阵列运行控制位。
该位通过软件置位,用来起动PCA计数器阵列计数。
该位通过软件清零,用来关闭PCA计数器。
CCF1:PCA模块1中断标志。
当出现匹配或捕获时该位由硬件置位。
该位必须通过软件清零。
CCF0:PCA模块0中断标志。
当出现匹配或捕获时该位由硬件置位。
该位必须通过软件清零。
3. 3.PCA比较/捕获寄存器CCAPM0和CCAPM1PCA模块0的比较/捕获寄存器的格式如下:CCAPM0:PCA模块0的比较/捕获寄存器B7:保留位将来之用。
ECOM0:允许比较器功能控制位。
STC12内部PWM使用方法解析
STC12内部PWM使用方法解析首先说一下PWM是一个什么样的东西,PWM的中文名字叫做“脉宽调制”,也就是说呢,我们的电路有两种状态,通或者不通,我们用单片机控制输出高电平低电平从而控制电路的通断来达到我们想要的某种模拟电路特有的效果的一种技术。
我们举个例子,比如说我们的直流电机直接接在五伏的电源上,要么全速运转,要么不转。
那我们怎样实现调速呢?我们可以通过单片机来控制这个电路,让电机电路通一段时间断一段时间。
比如说通一秒断一秒,那么电机的速度就会比全速运转时候低,不断改变这个通断之间的间隔时间,我们就可以达到一种调速的效果。
下面呢,我们就切入正题。
STC12C5A60S2这款单片机(下面说成12系列单片机),与89系列的单片机相比,它的内部增加了独立的PCA(计数器阵列,说简单点就是好几个计数器)或者说PWM模块,通过配置相关的特殊功能寄存器,我们可以实现一些额外的功能,比如说计时器,高脉冲输出,PWM输出等,如果我们用这种方法来实现PWM功能,要比用定时器加中断组合那种方法简单很多。
大家可能都看过那个技术文档,但是不得不说它的技术文档写的真是让人不敢恭维。
经过查阅资料,还有逛论坛,我大致了解了PCA模块,它到底是什么样一个东西,应当怎样用等。
下面我把相关的内容分享给大家,与大家交流一下。
如果有什么不对的地方,大家可以评论里边指出来,一定虚心思考。
我们看官方对PCA模块的介绍:对于图片里边提到的定时器的概念,大家已经非常熟悉了,而“捕获/比较器”,这个东西对我们来说可能比较生疏,其实通俗的说呢,在PWM功能里边,模块0与模块1里边的捕获比较器,就是一个比较大小的硬件装置。
假如有一个固定的值装在模块0的特殊功能寄存器里边,有一个外部来的外来值与它里边装的那个值不停的进行比较大小这种操作,如果外来的值比较小,那么这个比较大小的装置就会输出0,反之输出1。
(至于捕获模式,我们暂时用不到,他们其实是一个可以检测到相应引脚高低电平变化的硬件装置,我们知道,引脚拉高拉低并不是一下子就完成的,无论拉高或拉低,都有一定的上升或下降沿,捕获其实捕获的就是这种上升下降沿,一旦捕获到,可以触发相应的中断,这些都由软件决定。
(仅供参考)控制步进电机STC12C5A60S2输出变频PWM
#include <stc12c5a60s2.h>#define FOSC 12000000Lunsigned char length,HZ;unsigned long PCHZ,count,m,lowest_PCHZ,Acc_m,Dec_m,L_PCHZ; unsigned long Acc_Inplace,Dec_Inplace;unsigned long increasing,decline;sbit direction=P0^6;sbit PWM0=P1^3;sbit enable=P3^2;sbit led1=P0^7;unsigned char yb,syb;bit pause_busy,stop_busy,busy,Timer1_busy;bit pause,go_ahead,stop,reset;bit USART_Flag=0;bit Acc_flag,Dec_flag;bit flag=0;bit Trans_pause_busy;void ENPCA_Init() //PWM输出初始化函数{CCON=0 ;CMOD |=0x05;CL=0;CH=0;CR=1;}void Timer0_Init(unsigned char tt){AUXR |=0x80;TMOD |=0x02;TH0= tt;TL0= tt;TR0= 1;}void send(unsigned char send_data) //串口发送函数{SBUF=send_data;while(!TI);}void PWM_OUT(unsigned char channel,unsigned char start_value) //PWM 输出函数{if(channel == 0){CCAP0L = start_value; //Set the initial value same as CCAP0HCCAP0H = start_value; //25% Duty CycleCCAPM0 = 0x53; //0x42 Setup PCA module 0 in PWM mode }if(channel == 1){CCAP1L = start_value; //Set the initial value same as CCAP1HCCAP1H = start_value; //25% Duty CycleCCAPM1 = 0x73; //0x42 Setup PCA module 1 in PWM mode }}void Set_Function1() //数据设置函数{if(set_data[2]==0xFF){flag=0;Dec_flag=0;Acc_flag=0;if(!busy){count=set_data[3]*65536+set_data[4]*256+set_data[5];PCHZ=set_data[6]*256+set_data[7];HZ=(256-(FOSC/256/PCHZ));direction=(set_data[8]&0x01);enable=(set_data[8]&0x02)>>1;if(enable){PWM_OUT(0,0X80);ENPCA_Init();Timer0_Init(HZ);}}else{send('D');}}else if (set_data[2]==0xFE){Acc_flag=1;flag=1;count=set_data[3]*65536+set_data[4]*256+set_data[5];lowest_PCHZ=set_data[6]*256+set_data[7];L_PCHZ=lowest_PCHZ;HZ=(256-(FOSC/256/lowest_PCHZ));PCHZ=set_data[8]*256+set_data[9];direction=(set_data[10]&0x01);enable=(set_data[10]&0x02)>>1;if(enable){PWM_OUT(0,0x80);ENPCA_Init();Timer0_Init(HZ);}}else{if(!busy){if(set_data[2]<=0x04){flag=0;Acc_flag=0;Dec_flag=0;if(set_data[2]==0x01){count=set_data[3]*65536+set_data[4]*256+set_data[5];}else if(set_data[2]==0x02){PCHZ=set_data[3]*256+set_data[4];HZ=(256-(FOSC/256/PCHZ));}else if(set_data[2]==0x03){direction=(set_data[3]&0x01);}else if(set_data[2]==0x04){enable=(set_data[3]&0x01);}if(enable){PWM_OUT(0,0X80);ENPCA_Init();Timer0_Init(HZ);}}else{flag=1;Dec_flag=0;Acc_flag=1;if(set_data[2]==0x05){count=set_data[3]*65536+set_data[4]*256+set_data[5];}if(set_data[2]==0x06){lowest_PCHZ=set_data[6]*256+set_data[7];L_PCHZ=lowest_PCHZ;HZ=(256-(FOSC/256/lowest_PCHZ));}else if(set_data[2]==0x07){PCHZ=set_data[8]*256+set_data[9];}else if(set_data[2]==0x08){direction=(set_data[3]&0x01);}else if(set_data[2]==0x09){enable=(set_data[3]&0x01);}if(enable){Acc_flag=1;PWM_OUT(0,0X80);ENPCA_Init();Timer0_Init(HZ);}}}else{if(set_data[2]==0x0A){pause=set_data[3]&0x01;}if(set_data[2]==0x0B){go_ahead=set_data[3]&0x01;}if(set_data[2]==0x0C){stop=set_data[3]&0x01;}if(set_data[2]==0x0D){reset=set_data[3]&0x01;}}}}void Modbus_Init(unsigned char cc) //moudbus协议转换函数{unsigned char i,t;for(i=1;i<=(cc-3);i++){if((rsbuf[i]>=0x30)&&(rsbuf[i]<=0x39)){if(i%2){rsbuf[i]=(rsbuf[i]-0x30)<<4;}else{rsbuf[i]=rsbuf[i]-0x30;}}else if((rsbuf[i]>=0x41)&&(rsbuf[i]<=0x46)){if(i%2){rsbuf[i]=(rsbuf[i]-0x37)<<4;}else{rsbuf[i]=rsbuf[i]-0x37;}}else if((rsbuf[i]>=0x61)&&(rsbuf[i]<=0x66)){if(i%2){rsbuf[i]=(rsbuf[i]-0x47)<<4;}else{rsbuf[i]=rsbuf[i]-0x47;}}}t=1;for(i=1;i<=(cc-3);i=i+2){if(t<=((cc-3)>>1)){set_data[t]=rsbuf[i]+rsbuf[i+1];t++;}else{t=0;}}}void Serical_Init() //串口初始化函数{PCON |= 0x80; //使能波特率倍速位SMODSCON = 0x50; //8位数据,可变波特率BRT = 0xFA; //设定独立波特率发生器重装值AUXR |= 0x04; //独立波特率发生器时钟为Fosc,即1TAUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器AUXR |= 0x10; //启动独立波特率发生器ES=1;}void Clear_Function() //PWM输出定位清空函数{if(m==1){send('4');}if(m>=count){TR0=0;CR=0;busy=0;enable=0;send(m/65536);send((m%65536)/256);send(((m%65536)%256)%256);m=0;PCHZ=0;count=1;lowest_PCHZ=0;Dec_flag=0;Acc_flag=0;flag=0;}if(flag){if(lowest_PCHZ<PCHZ){HZ=(256-(FOSC/256/lowest_PCHZ));Timer0_Init(HZ);}else{Acc_flag=0;Dec_flag=0;HZ=(256-(FOSC/256/PCHZ));Timer0_Init(HZ);}if(m>=count-Acc_m){Dec_flag=1;Acc_flag=0;if(lowest_PCHZ<=L_PCHZ){Dec_flag=0;lowest_PCHZ=L_PCHZ;}}}}void USART_Data() //串口接收数据处理函数{unsigned char ii;for(ii=0;ii<=length-1;ii++){ssbuf[ii]=rsbuf[ii];}Modbus_Init(length);if(set_data[1]==0x01){Set_Function1();yb=0;}}void Pause_Function() //PWM输出中暂停处理函数{if(Acc_flag | Dec_flag){CR=0;TR0=0;count=count-m;send(m/65536);send((m%65536)/256);send(((m%65536)%256)%256);m=0;Trans_pause_busy=1;}else{CR=0;TR0=0;count=count-m;send(m/65536);send((m%65536)/256);send(((m%65536)%256)%256);m=0;pause_busy=1;}}void Go_ahead_Function() //PWM输出暂停后继续输出函数{if(Trans_pause_busy){CR=1;TR0=1;flag=1;Trans_pause_busy=0;}else if (pause_busy){CR=1;TR0=1;flag=0;pause_busy=0;}}void Stop_Function() //PWM输出停止函数{stop_busy=1;CR=0;TR0=0;count=count-m;m=0;}void Reset_Function() //PWM输出复位函数{if(stop_busy){if(direction){direction=0;flag=0;Timer0_Init(15);TR0=1;CR=1;stop_busy=0;}else{flag=0;Timer0_Init(15);TR0=1;CR=1;stop_busy=0;}}}void main() //程序运行主函数{enable=0;direction=0;P2=0x01;Serical_Init();EA=1;busy=0;CR=0;IPH |=0x10;PS =1;while(1){if(USART_Flag) //判断是否接收到数据{USART_Flag=0; //判断标记位清零USART_Data(); //处理接收数据}Clear_Function();if(pause) //判断是否接收到暂停指令{pause=0;Pause_Function();}if(go_ahead) //判断是否接收到继续指令{go_ahead=0;Go_ahead_Function();}if(stop) //判断是否接收到停止指令{stop=0;Stop_Function();}if(reset) //判断是否接收到复位指令{reset=0;Reset_Function();}}}void Serical_Interrupt() interrupt 4 //串口中断函数{unsigned char temp,temp_next;if(RI){RI=0;temp=SBUF;rsbuf[yb]=temp;yb++;led1=0;if((rsbuf[0]==':')&&(temp_next=0x0D)&&(temp==0x0A)){length=yb;USART_Flag=1;}temp_next=temp;}if(TI){TI=0;}}void PCA_Interrupt ()interrupt 7 //PWM输出中断函数{CF=0;CCF0=0;m++;busy=1;if(Acc_flag){{lowest_PCHZ++;}if(lowest_PCHZ==PCHZ){Acc_m=m;Acc_flag=0;}}if(Dec_flag){{lowest_PCHZ--;}}}。
STC12C5A60S2内部PWM应用
【PWM】.实例一:电路图如上,该程序的功能是利用按键S1对LED的亮度进行调节。
程序如下:#include"STC12C5A.h"//注意这个头文件,用reg52是不行的,如果你没有的话,可以去百// //度文档里搜索“STC12C5A系列单片机头文件”,有我共享的头文件。
void delay(unsigned int cnt){unsigned char i;for(;cnt>0;cnt--)for(i=0;i<250;i++);}void main(){CCON=0; //PCA初始化CL=0; //PCA的16位计数器低八位CH=0; //PCA的16位计数器高八位CMOD=0x00; //选择系统时钟/12 为计数脉冲,则PWM的频率f=sysclk/256/12;CCAP0H=0x80; // 占空比控制CCAP0L=0x80;PCA_PWM0=0x00; //控制占空比的第九位为0CCAPM0=0x42; //允许P13作为PWM输出CR=1; //启动PCA计数器while(1){if(P10==0){delay(200);while(P10==0);CCAP0H+=10; //占空比调节CCAP0L+=10;}}}实例二:两个文件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晶振下,stc10f系列(单周期指令)的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(STC12C5A60S2系列)sfr CCAPM1 = 0xDB; //PCA模块1模式寄存器//模块1对应P1.4/CEX1/PCA1/PWM1(STC12C5A60S2系列)sfr CL = 0xE9; //PCA 定时寄存器低位sfr CH = 0xF9; //PCA 定时寄存器高位sfr CCAP0L = 0xEA; //PCA模块0的捕获寄存器低位sfr CCAP0H = 0xFA; //PCA模块0的捕获寄存器高位sfr CCAP1L = 0xEB; //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){CCAP0L = 0XC0;CCAP0H = 0XC0; //模块0初始输出占空因数为25%CCAP1L = 0XC0;CCAP1H = 0XC0; //模块1初始输出占空因数为25%if(module==0){switch(mode){case 0: CCAPM0 = 0X42;break; //模块0设置为8位PWM输出,无中断case 1: CCAPM0 = 0X53;break; //模块0设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = 0X63;break; //模块0设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = 0X73;break; //模块0设置为8位PWM 输出,跳变沿产生中断default: break;}}elseif(module==1){switch(mode){case 0: CCAPM1 = 0X42;break; //模块1设置为8位PWM输出,无中断case 1: CCAPM1 = 0X53;break; //模块1设置为8位PWM输出,下降沿产生中断case 2: CCAPM1 = 0X63;break; //模块1设置为8位PWM输出,上升沿产生中断case 3: CCAPM1 = 0X73;break; //模块1设置为8位PWM输出,跳变沿产生中断default: break;}}elseif(module==2){switch(mode){case 0: CCAPM0 = CCAPM1 = 0X42;break; //模块0和1设置为8位PWM输出,无中断case 1: CCAPM0 = CCAPM1 = 0X53;break; //模块0和1设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = CCAPM1 = 0X63;break; //模块0和1设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = CCAPM1 = 0X73;break; //模块0和1设置为8位PWM输出,跳变沿产生中断default: break;}}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(0,0); // 模块0,设置为PWM输出,无中断,初始占空因素为25%while(1){DelayMs(250);}}PwmDrive_12C5A.c#include <intrins.h>#define U8 unsigned charsfr CCON = 0xD8; //PCA控制寄存器sfr CMOD = 0xD9; //PCA模式寄存器sfr CCAPM0 = 0xDA; //PCA模块0模式寄存器//模块0对应P1.3/CEX0/PCA0/PWM0(STC12C5A60S2系列)sfr CCAPM1 = 0xDB; //PCA模块1模式寄存器//模块1对应P1.4/CEX1/PCA1/PWM1(STC12C5A60S2系列)sfr CL = 0xE9; //PCA 定时寄存器低位sfr CH = 0xF9; //PCA 定时寄存器高位sfr CCAP0L = 0xEA; //PCA模块0的捕获寄存器低位sfr CCAP0H = 0xFA; //PCA模块0的捕获寄存器高位sfr CCAP1L = 0xEB; //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){CCAP0L = 0XC0;CCAP0H = 0XC0; //模块0初始输出占空因数为25%CCAP1L = 0XC0;CCAP1H = 0XC0; //模块1初始输出占空因数为25%if(module==0){switch(mode){case 0: CCAPM0 = 0X42;break; //模块0设置为8位PWM输出,无中断case 1: CCAPM0 = 0X53;break; //模块0设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = 0X63;break; //模块0设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = 0X73;break; //模块0设置为8位PWM输出,跳变沿产生中断default: break;}}elseif(module==1){switch(mode){case 0: CCAPM1 = 0X42;break; //模块1设置为8位PWM输出,无中断case 1: CCAPM1 = 0X53;break; //模块1设置为8位PWM输出,下降沿产生中断case 2: CCAPM1 = 0X63;break; //模块1设置为8位PWM输出,上升沿产生中断case 3: CCAPM1 = 0X73;break; //模块1设置为8位PWM输出,跳变沿产生中断default: break;}}elseif(module==2){switch(mode){case 0: CCAPM0 = CCAPM1 = 0X42;break; //模块0和1设置为8位PWM输出,无中断case 1: CCAPM0 = CCAPM1 = 0X53;break; //模块0和1设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = CCAPM1 = 0X63;break; //模块0和1设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = CCAPM1 = 0X73;break; //模块0和1设置为8位PWM输出,跳变沿产生中断default: break;}}CR=1; //PCA计数器开始计数}void PCA_Intrrpt(void) interrupt 7{if(CCF0) CCF0=0;if(CCF1) CCF1=0; //软件清零if(CF) CF=0; //软件清零}(注:文档可能无法思考全面,请浏览后下载,供参考。
STC12C5A60S2程序实现0-256分之一晶振任意频率PWM输出
STC12C5A60S2程序实现0-256分之一晶振任意频率PWM输出
//头文件STC12C5A.h可在网上下载#include \#define uint unsigned int #define uchar unsigned char uchar t=0;
sbit sign=CCON ;//此位为预留位置,开发用作表示振动片工作模式,0为一
//般模式,1为ADC模式
void init_T0(void);//初始化T0 void init_T1(void);//初始化[T1
void init_INT0(void);//初始化外部中断0 void init_INT1(void);//初始化外部中断1 void init_PCA(void);//初始化PCA模块void init_ADC(void);//初始化A/D转化模块void main(void) {
sign=0;//默认工作在固定模式P17=1;//开始时P3 输出为高电平EA=1;//开总中断
init_T0();//初始化T0 init_T1();//初始化T1
init_INT0();//初始化外部中断0 init_INT1();//初始化外部中断 1 init_PCA();//初始化PCA模块CR=1; //开启PCA计数器init_ADC(); //初始化A/D转化模块while(1) { if(sign==1) //工作在ADC模式{
if(ADC_CONTR//防止干扰信号误动作。
完整word版,STC12C5A60S2程序实现0-256分之一晶振任意频率PWM输出
//头文件STC12C5A.h可在网上下载#include "STC12C5A.H"#define uint unsigned int#define uchar unsigned charuchar t=0;sbit sign=CCON^2;//此位为预留位置,开发用作表示振动片工作模式,0为一//般模式,1为ADC模式void init_T0(void);//初始化T0void init_T1(void);//初始化[T1void init_INT0(void);//初始化外部中断0void init_INT1(void);//初始化外部中断1void init_PCA(void);//初始化PCA模块void init_ADC(void);//初始化A/D转化模块void main(void){sign=0;//默认工作在固定模式P17=1;//开始时P3^0输出为高电平EA=1;//开总中断init_T0();//初始化T0init_T1();//初始化T1init_INT0();//初始化外部中断0init_INT1();//初始化外部中断1init_PCA();//初始化PCA模块CR=1; //开启PCA计数器init_ADC(); //初始化A/D转化模块while(1){if(sign==1)//工作在ADC模式{if(ADC_CONTR&ADC_FLAG!=0)//转换结束{TH0=ADC_RES; //溢出率与初值成正比TL0=ADC_RES;ADC_CONTR=ADC_CONTR & 0xE7;//将ADC_FLAG(转换结//束标志位)与ADC_START清零,其余位不变ADC_CONTR=ADC_CONTR | 0x08;//将ADC_START置1 }}else //工作在固定模式{TH0=0x30; //输出一固定频率的PWM波TL0=0x30;}}}void init_T0(void)//T0做PCA的时钟源输入{//通过改变定时器0溢出率实现可调频率的PWM输出TMOD=0x02;//定时器0工作在方式2,8位定时计数器自动重装载TH0=0x80;//设置T0定时所对应的初值TL0=0x80;//设置T0每次定时结束后重装载的值ET0=1;//允许定时器0中断TR0=1;//定时器0开始计数}void init_T1(void)//T1定时100ms,用于产生呼气吸气脉冲{TMOD=TMOD|0x10;//设置定时器1的工作方式为方式2且不改变定时器0的工作方式TH1=0x3c; //设置定时100ms的处初值TL1=0xb0;ET1=1;//允许定时器1中断TR1=1; //定时器1开始计数}void init_INT0(void){IT0=1;//由下降沿触发,输入引脚P3^2EX0=1;//开外部中断0}void init_INT1(void){IT1=1; //由下降沿触发,输入引脚P3^3EX1=1; //开外部中断1}void init_PCA(void){CMOD=0x04; //CIDL=0(D7):空闲模式下继续计数,D4~D6不用//CPS2/CPS1/CPS0(D3~D1)=010,选择T0做PCA时钟源输入//ECF(D0)=0,关PCA计数器溢出中断CCF1=0; //清零PCA模块1中断标志位CCF0=0; //清零PCA模块0中断标志位CR=0; //关闭PCA计数器CH=0;//PCA计数器高8位置零CL=0; //PCA计数器低8位置零CCAPM0=0X42;//PCA模块0的工作模式寄存器设置为0X42表示8位PWM无中断CCAP0H=0x80; //设置PWM波的占空比为0.5CCAP0L=0x80; //溢出后会将CCAP0H中值赋给CCAP0LCCAPM1=0x31; //PCA模块1扩展为上升沿下降沿均可触发的外部中断}void init_ADC(void){uint i;for(i=10000;i!=0;i--)//若晶振为6MHZ,是延时20ms等待ADC模块内部模拟电源稳定{;}ADC_CONTR=0x80;//开ADC模块电源并选择P1^0作为模拟量输入引脚P1ASF=0x01; //P1口模拟量功能设置寄存器:使用P1^0的模拟量功能AUXR1=AUXR1 & 0xfb;//ADRJ=0,ADC_RES存放A/D转换结果高8位//ADC_RESL存放A/D转换结果低8位ADC_RES=0; //检测前将其清零ADC_RESL=0;//检测前将其清零EADC=1; //开A/D转换中断}void INT0_ISR(void) interrupt 0 //外部中断0服务程序{sign=0;//工作在固定模式ADC_CONTR=ADC_CONTR&0xF7;//关闭ADC电源}void INT1_ISR(void) interrupt 2 //外部中断1服务程序{sign=1;//工作在ADC模式ADC_CONTR|=0x08; //打开ADC电源,由用户决定PWM频率}void T1_ISR(void) interrupt 3 //定时器1中断服务程序{TH1=0x3C; //工作在方式1溢出后不能自动重装载TL1=0xB0;t++;if(t==20)//2s后输出低电平P17=!P17;if(t==50){t=0;//5s为一个周期P17=!P17;}}void PCA_ISR(void) interrupt 7{if(CCF1==1)//PCA模块1中断响应{if(P14==0)//判断是上升沿触发还是下降沿触发,等于0为下降沿触发{while(t!=25); //延时0.5sCCAP0H=0x80; //设置PWM波的占空比为0.5CCAP0L=0x80;}else//上升沿触发{CCAP0H=0xFF; //PWM输出低电平CCAP0L=0xFF;}CCF1=0;elseCCF0=0;//防止干扰信号误动作}}。
STC12C5A60S2的AD转换,PWM电压控制,液晶显示程序
/*---------------------------------------------------------------------------------------------------------------------------*//*--************************功能【AD转换,PWM电压控制,液晶显示】**************************--*/ /*--************************芯片:【STC12C5A60S2】******************************--*//*--************************液晶:【LCD1602】***********************************--*//*--************************ADC管脚:【P1.7 】***************************--*//*--************************检测范围:【0.00~12.5V】***************************--*//*---------------------------------------------------------------------------------------------------------------------------*/#include "stc12c5a60s2.h"#include "intrins.h"#define uint unsigned int#define uchar unsigned char#define _Nop() _nop_()/*------------------------以下为LCD1602显示模块定义-----------------------*/unsigned char data_char_table[]= {"0123456789ABCDEF"}; //LCD数据unsigned char Lcd_Dis1_table[] = {"Setvalue: V"}; //第一行显示框架unsigned char pos_char_table[] = {" 9A.C0 "}; // 显示位置unsigned char Lcd_Dis2_table[] = {"V oltage : V"}; //第二行显示框架unsigned char num_char_table[] = {" 9A.CD V"}; // 显示位置float show;float NUM;static uchar ldata=50; //作为显示的数据sbit lcd_rs_port = P2^0; //定义LCD控制端口,根据硬件调整sbit lcd_rw_port = P2^1;sbit lcd_en_port = P2^2;#define lcd_data_port P0sbit key1 = P3^7; //定义按键1sbit key2 = P3^6; //定义按键2sbit key3 = P3^5; //定义按键3sbit key4 = P3^4; //定义按键4sbit key5 = P3^3; //定义按键5sbit key6 = P3^2; //定义按键6/************定义相应操作位***************/#define ADC_POWER 0x80 //ADC电源控制位,0:关闭,1:打开#define ADC_FLAG 0x10 //ADC结束标志位#define ADC_START 0x08 //ADC启动控制位#define ADC_SPEEDLL 0x00 //540 clocks___________选择转换速度/*------------------------以下为相关函数声明------------------------------*/void InitADC(); //ADC初始化uint GetADCResult(uchar ch);void Delay(uint n); //延时程序void delay_1ms(uchar x);void lcd_delay(uchar ms); //LCD1602 延时void lcd_busy_wait(); //LCD1602 忙等待void lcd_command_write(uint command); //LCD1602 命令字写入void lcd_system_reset(); //LCD1602 初始化void lcd_char_write(uint x_pos,y_pos,lcd_dat); //LCD1602 字符写入void lcd_bad_check(); //LCD1602 坏点检查void Num_to_Disp(uint i, uint Num); //显示数据处理void LcdDisp(uint j, uint num); //液晶显示函数void DelayMs(uchar ms);void init_PWM();void PWM1_change(uchar type,uchar change);void PWM1_set(uchar empty);/*-------------------------------- ADC 取值------------------------------*/uint GetADCResult(uchar ch){ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;_nop_(); //Must wait before inquiry_nop_();_nop_();_nop_();while (!(ADC_CONTR & ADC_FLAG)); //Wait complete flagADC_CONTR &= ADC_FLAG; //Close ADCreturn (ADC_RES*4 + ADC_RESL); //Return ADC result}/*---------------------------- 初始化ADC特殊功能寄存器-------------------*/void InitADC( ){P1ASF = 0x80; //Set P1.7 as input portADC_RES = 0; //Clear previous resultADC_RESL = 0;ADC_CONTR = ADC_POWER | ADC_SPEEDLL ;Delay(20); //ADC power-on delay and Start A/D conversion}/*---------------------------- LCD1602相应函数---------------------------*////////////////以下为LCD显示数据处理/////////////////void Num_to_Disp(uint i, uint Num){int xx, yy, zz;NUM = (Num * 4.68/ 1024.0); //计算公式:10-bit A/D Conversion Result = 1024 x (Vin / Vcc) NUM =NUM *29.1/9.9;xx = (int)NUM;yy = (int)((NUM - (float)(xx)) * 10);zz = (int)((NUM - (float)(xx)) * 100)%10;/********************第一行数字*******************************/pos_char_table[9]= data_char_table[i/100]; //输入值十位pos_char_table[10]= data_char_table[i%100/10]; //输入值个位pos_char_table[12]= data_char_table[i%10]; //输入值小数点后一位/********************第二行数字*******************************/num_char_table[9] = data_char_table[xx / 10]; //电压值十位num_char_table[10]= data_char_table[xx % 10]; //电压值个位num_char_table[12]= data_char_table[yy]; //电压值小数点后一位num_char_table[13]= data_char_table[zz]; //电压值小数点后两位}//////////////////以下为LCD显示////////////////////void LcdDisp(uint j, uint num){uint i=0;for (i=0;i<16;i++){lcd_char_write(i,0,Lcd_Dis1_table[i]);lcd_char_write(i,1,Lcd_Dis2_table[i]); //显示框架(固定文字)}Num_to_Disp(j, num);for(i = 9; i < 14; i++){lcd_char_write(i,0,pos_char_table[i]); //显示输入值}for(i = 9; i < 14; i++){lcd_char_write(i,1,num_char_table[i]); //显示电压}delay_1ms(100);}//////////////以下是LCD1602驱动程序////////////////void lcd_delay(uchar ms) /*LCD1602 延时*/{uchar j;while(ms--){for(j=0;j<250;j++){;}}}void lcd_busy_wait() /*LCD1602 忙等待*/{lcd_rs_port = 0;lcd_rw_port = 1;lcd_en_port = 1;lcd_data_port = 0xff;while (lcd_data_port&0x80);lcd_en_port = 0;}void lcd_command_write(uint command) /*LCD1602 命令字写入*/ {lcd_busy_wait();lcd_rs_port = 0;lcd_rw_port = 0;lcd_en_port = 0;lcd_data_port = command;lcd_en_port = 1;lcd_en_port = 0;}void lcd_system_reset() /*LCD1602 初始化*/{lcd_delay(20);lcd_command_write(0x38);lcd_delay(100);lcd_command_write(0x38);lcd_delay(50);lcd_command_write(0x38);lcd_delay(10);lcd_command_write(0x08);lcd_command_write(0x01);lcd_command_write(0x06);lcd_command_write(0x0c);}void lcd_char_write(uint x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/ {x_pos &= 0x0f; /* X位置范围0~15 */y_pos &= 0x01; /* Y位置范围0~ 1 */if(y_pos==1) x_pos += 0x40;x_pos += 0x80;lcd_command_write(x_pos);lcd_busy_wait();lcd_rs_port = 1;lcd_rw_port = 0;lcd_en_port = 0;lcd_data_port = lcd_dat;lcd_en_port = 1;lcd_en_port = 0;}void lcd_bad_check() /*LCD1602 坏点检查*/{char i,j;for(i=0;i<2;i++){for(j=0;j<16;j++) {lcd_char_write(j,i,0xff);}}lcd_delay(200);lcd_delay(200);lcd_delay(200);lcd_delay(100);lcd_delay(200);lcd_command_write(0x01); /* clear lcd disp */}//////////////////以上是LCD1602驱动程序/////////////////*----------------------------- 延时程序---------------------------*/ void Delay(uint n){uint x;while (n--){x = 500;while (x--);}}/*1MS为单位的延时程序*/void delay_1ms(uchar x){uchar j;while(x--){for(j=0;j<125;j++){;}}}void DelayMs(uchar ms) //延时程序{uint i;while(ms--){for(i = 0; i < 850; i++);}}void init_PWM(){CCON=0X00;CH=0;CL=0;CMOD=0X02; //0X00:以系统时钟/12 为时钟源,0X02:系统时钟/2,0x08:系统时钟PWM1_set(0X80);//起始占空比,0XC0:占空比为25%,0X80:占空比为50%,0X40:占空比为75% CCAPM1=0X42; //0X42:8位PWM P1.4输出,无中断;0X53:8位PWM输出,下降沿产生中断;0X63:上升沿产生中断;0X73:跳变沿产生中断CR=1; //计时器开始工作}void PWM1_set(uchar empty) //直接设置占空比{CCAP1L=empty;CCAP1H=empty;}void PWM1_change(uchar type,uchar change) //type=0减占空比,1增加占空比change: 0X0C约5%,0X05约2%{if(type==0){CCAP1L+=change;CCAP1H+=change;}else{CCAP1L-=change;CCAP1H-=change;}}void main(){init_PWM(); //初始化,PWM输出lcd_system_reset(); //LCD1602 初始化lcd_bad_check(); //LCD1602 坏点检查InitADC(); //初始化ADC特殊功能寄存器while(1) //按键增减PWM占空比{if(key1==0) //按键1按下{DelayMs(1); //按键消抖while(key1==0); //按键释放才跳出执行下一步ldata++; //显示数据加0.1}else if(key2==0) //按键2按下{DelayMs(1); //按键消抖while(key2==0); //按键释放才跳出执行下一步ldata--; //显示数据减0.1}else if(key3==0) //按键3按下{DelayMs(1); //按键消抖while(key3==0); //按键释放才跳出执行下一步ldata+=10; //显示数据加1}else if(key4==0) //按键4按下{DelayMs(1); //按键消抖while(key4==0); //按键释放才跳出执行下一步ldata-=10; //显示数据减1}else if(key5==0) //按键5按下{DelayMs(1); //按键消抖while(key5==0); //按键释放才跳出执行下一步ldata=0; //清0}LcdDisp(ldata,GetADCResult(7)); //液晶1602显示输入电压值和AD采集电压值(P1.7)NUM=10*NUM;show=ldata;if((NUM<(show-0.1))||(NUM>(show+0.1))){if(NUM<(show-0.1)){if((show-0.1)-NUM>1)PWM1_change(1,0X05);elsePWM1_change(1,0X01);}else{if(NUM-(show+0.1)>1)PWM1_change(0,0X05);elsePWM1_change(0,0X01);}Delay(500);}else{Delay(2000);}}}。
STC12C5A60S2-PWM调节
#include<STC12C5A60S2.H> //头文件/******************************************************************************************** 函数名:PWM初始化函数调用:PWM_init();参数:无返回值:无结果:将PCA初始化为PWM模式,初始占空比为0备注:需要更多路PWM输出直接插入CCAPnH和CCAPnL即可/*******************************************************************************************/ void PWM_init (void){CMOD=0x02; //设置PCA定时器CL=0x00;CH=0x00;CCAPM0=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)CCAP0L=0x00; //设置PWM0初始值与CCAP0H相同CCAP0H=0x00; // PWM0初始时为0//CCAPM1=0x42; //PWM1设置PCA工作方式为PWM方式(使用时删除//)//CCA P1L=0x00; //设置PWM1初始值与CCAP0H相同//CCAP1H=0x00; // PWM1初始时为0//CCAPM2=0x42; //PWM2设置PCA工作方式为PWM方式//CCAP2L=0x00; //设置PWM2初始值与CCAP0H相同//CCAP2H=0x00; // PWM2初始时为0//CCAPM3=0x42; //PWM3设置PCA工作方式为PWM方式//CCAP3L=0x00; //设置PWM3初始值与CCAP0H相同//CCAP3H=0x00; // PWM3初始时为0CR=1; //启动PCA定时器}/*******************************************************************************************/ /********************************************************************************************函数名:PWM0占空比设置函数调用:PWM0_set();参数:0x00~0xFF(亦可用0~255)返回值:无结果:设置PWM模式占空比,为0时全部高电平,为1时全部低电平备注:如果需要PWM1的设置函数,只要把CCAP0L和CCAP0H中的0改为1即可/*******************************************************************************************/ void PWM0_set (unsigned char a){CCAP0L= a; //设置值直接写入CCAP0LCCAP0H= a; //设置值直接写入CCAP0H}/*******************************************************************************************/ /******************************************************************************************* 函数名:主函数调用:无参数:无返回值:无结果:程序开始处,无限循环备注:******************************************************************************************/ void main (void){while(1){PWM_init(); //PWM初始化PWM0_set(0x7F); //设置PWM占空比,总共255,除以2,转换成十六进制得7F}}/******************************************************************************************** **/。
STC12内部PWM使用方法解析
STC12内部PWM使用方法解析STC12系列单片机是深圳市袋鼠电子股份有限公司出品的一款高性价比的51单片机系列产品。
STC12单片机内部集成了丰富的外设,包括多个定时器/计数器、串口通信接口、ADC(模数转换器)和PWM(脉冲宽度调制)输出等功能。
本篇文章将着重介绍STC12单片机的内部PWM模块的使用方法。
PWM是一种通过改变脉冲信号的占空比来控制电机、LED等器件的工作状态的技术。
在STC12单片机中,可以通过硬件PWM或软件PWM的方式来实现对外设的控制。
硬件PWM是由单片机内部的PWM模块自动产生的脉冲信号,不需要单片机的软件干预;而软件PWM是通过软件编程来实现对IO口的高低电平切换,从而模拟出脉冲信号。
下文将详细介绍STC12单片机的内部PWM模块的使用方法。
1. 定时器/计数器的选择:STC12单片机中有多个定时器/计数器模块可供选择,例如Timer0、Timer1、Timer2等。
这些定时器/计数器模块可用于产生PWM信号的时钟源。
一般情况下,Timer2是最常用的选择,因为它可以独立设置工作模式,而不会干扰其他外设的工作。
2.PWM的工作模式选择:STC12单片机的PWM模块提供了多种工作模式选择,如16位定时器模式、8位定时器模式、PCA脉冲宽度调制模式等。
在选择工作模式时,需要考虑到要控制的外设的需求,并根据外设的工作要求选择合适的PWM输出模式。
3.PWM的占空比设置:PWM的占空比是指PWM信号中高电平的时间占整个周期的比例。
在STC12单片机中,可以通过读写PWM模块相应的寄存器来设置占空比。
具体设置方法可参考STC12的相关资料或数据手册。
4.PWM输出管脚设置:在STC12单片机中,PWM信号可以通过多个IO口输出。
使用PWM输出功能时,需要将相应的IO口设置为PWM输出模式,并将PWM输出模块与IO口进行配置。
具体配置方法可参考STC12的开发工具或相关资料。
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单片机pwm应用
1.PCA工作模式寄存器CMODPCA工作模式寄存器的格式如下:CMOD:PCA工作模式寄存器CIDL:空闲模式下是否停止PCA计数的控制位当CIDL=0时,空闲模式下PCA计数器继续工作;当CIDL=1时,空闲模式下PCA计数器停止工作;CPS2、CPS1、CPS0:PCA计数脉冲源选择控制位。
PCA计数脉冲选择如下表所示:例如,CPS2/CPS1/CPS0=1/0/0时,PCA/PWM的时钟源是SYSclk,不是定时器0,PWM 的频率为SYSclk/265如果要用系统时钟/3来作为PCA的时钟源,应让T0工作在1T模式,计数3个脉冲即产生溢出。
如果此时使用内部RC作为系统时钟(室温情况下,5V单片机为11MHZ~15.5MHZ),可以输出14K~19K频率的PWM。
用T0的溢出可对系统时钟进行1~256级分频。
ECF:PCA计数溢出中断使能位。
当ECF=0时,禁止寄存器CCON中CF位的中断;当ECF=1时,允许寄存器CCON中CF位的中断。
2. 2. PCA控制寄存器CCONPCA控制寄存器的格式如下:CCON:PAC控制寄存器CF:PCA计数阵列溢出标志位。
当PCA计数器溢出时,CF由硬件位置。
如果CMOD 寄存器的ECF位置位,则CF标志可用来产生中断。
CF位可通过硬件或软件置位,但通过软件清零。
CR:PCA计数阵列运行控制位。
该位通过软件置位,用来起动PCA计数器阵列计数。
该位通过软件清零,用来关闭PCA计数器。
CCF1:PCA模块1中断标志。
当出现匹配或捕获时该位由硬件置位。
该位必须通过软件清零。
CCF0:PCA模块0中断标志。
当出现匹配或捕获时该位由硬件置位。
该位必须通过软件清零。
3. 3.PCA比较/捕获寄存器CCAPM0和CCAPM1PCA模块0的比较/捕获寄存器的格式如下:CCAPM0:PCA模块0的比较/捕获寄存器B7:保留位将来之用。
ECOM0:允许比较器功能控制位。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【PWM】.实例一:电路图如上,该程序的功能是利用按键S1对LED的亮度进行调节。
程序如下:#include"STC12C5A.h"//注意这个头文件,用reg52是不行的,如果你没有的话,可以去百// //度文档里搜索“STC12C5A系列单片机头文件”,有我共享的头文件。
void delay(unsigned int cnt){unsigned char i;for(;cnt>0;cnt--)for(i=0;i<250;i++);}void main(){CCON=0; //PCA初始化CL=0; //PCA的16位计数器低八位CH=0; //PCA的16位计数器高八位CMOD=0x00; //选择系统时钟/12 为计数脉冲,则PWM的频率f=sysclk/256/12;CCAP0H=0x80; // 占空比控制CCAP0L=0x80;PCA_PWM0=0x00; //控制占空比的第九位为0CCAPM0=0x42; //允许P13作为PWM输出CR=1; //启动PCA计数器while(1){if(P10==0){delay(200);while(P10==0);CCAP0H+=10; //占空比调节CCAP0L+=10;}}}实例二:两个文件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晶振下,stc10f系列(单周期指令)的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(STC12C5A60S2系列)sfr CCAPM1 = 0xDB; //PCA模块1模式寄存器//模块1对应P1.4/CEX1/PCA1/PWM1(STC12C5A60S2系列)sfr CL = 0xE9; //PCA 定时寄存器低位sfr CH = 0xF9; //PCA 定时寄存器高位sfr CCAP0L = 0xEA; //PCA模块0的捕获寄存器低位sfr CCAP0H = 0xFA; //PCA模块0的捕获寄存器高位sfr CCAP1L = 0xEB; //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){CCAP0L = 0XC0;CCAP0H = 0XC0; //模块0初始输出占空因数为25%CCAP1L = 0XC0;CCAP1H = 0XC0; //模块1初始输出占空因数为25%if(module==0){switch(mode){case 0: CCAPM0 = 0X42;break; //模块0设置为8位PWM输出,无中断case 1: CCAPM0 = 0X53;break; //模块0设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = 0X63;break; //模块0设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = 0X73;break; //模块0设置为8位PWM 输出,跳变沿产生中断default: break;}}elseif(module==1){switch(mode){case 0: CCAPM1 = 0X42;break; //模块1设置为8位PWM输出,无中断case 1: CCAPM1 = 0X53;break; //模块1设置为8位PWM输出,下降沿产生中断case 2: CCAPM1 = 0X63;break; //模块1设置为8位PWM输出,上升沿产生中断case 3: CCAPM1 = 0X73;break; //模块1设置为8位PWM输出,跳变沿产生中断default: break;}}elseif(module==2){switch(mode){case 0: CCAPM0 = CCAPM1 = 0X42;break; //模块0和1设置为8位PWM输出,无中断case 1: CCAPM0 = CCAPM1 = 0X53;break; //模块0和1设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = CCAPM1 = 0X63;break; //模块0和1设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = CCAPM1 = 0X73;break; //模块0和1设置为8位PWM输出,跳变沿产生中断default: break;}}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(0,0); // 模块0,设置为PWM输出,无中断,初始占空因素为25%while(1){DelayMs(250);}}PwmDrive_12C5A.c#include <intrins.h>#define U8 unsigned charsfr CCON = 0xD8; //PCA控制寄存器sfr CMOD = 0xD9; //PCA模式寄存器sfr CCAPM0 = 0xDA; //PCA模块0模式寄存器//模块0对应P1.3/CEX0/PCA0/PWM0(STC12C5A60S2系列)sfr CCAPM1 = 0xDB; //PCA模块1模式寄存器//模块1对应P1.4/CEX1/PCA1/PWM1(STC12C5A60S2系列)sfr CL = 0xE9; //PCA 定时寄存器低位sfr CH = 0xF9; //PCA 定时寄存器高位sfr CCAP0L = 0xEA; //PCA模块0的捕获寄存器低位sfr CCAP0H = 0xFA; //PCA模块0的捕获寄存器高位sfr CCAP1L = 0xEB; //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){CCAP0L = 0XC0;CCAP0H = 0XC0; //模块0初始输出占空因数为25%CCAP1L = 0XC0;CCAP1H = 0XC0; //模块1初始输出占空因数为25%if(module==0){switch(mode){case 0: CCAPM0 = 0X42;break; //模块0设置为8位PWM输出,无中断case 1: CCAPM0 = 0X53;break; //模块0设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = 0X63;break; //模块0设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = 0X73;break; //模块0设置为8位PWM输出,跳变沿产生中断default: break;}}elseif(module==1){switch(mode){case 0: CCAPM1 = 0X42;break; //模块1设置为8位PWM输出,无中断case 1: CCAPM1 = 0X53;break; //模块1设置为8位PWM输出,下降沿产生中断case 2: CCAPM1 = 0X63;break; //模块1设置为8位PWM输出,上升沿产生中断case 3: CCAPM1 = 0X73;break; //模块1设置为8位PWM输出,跳变沿产生中断default: break;}}elseif(module==2){switch(mode){case 0: CCAPM0 = CCAPM1 = 0X42;break; //模块0和1设置为8位PWM输出,无中断case 1: CCAPM0 = CCAPM1 = 0X53;break; //模块0和1设置为8位PWM输出,下降沿产生中断case 2: CCAPM0 = CCAPM1 = 0X63;break; //模块0和1设置为8位PWM输出,上升沿产生中断case 3: CCAPM0 = CCAPM1 = 0X73;break; //模块0和1设置为8位PWM输出,跳变沿产生中断default: break;}}CR=1; //PCA计数器开始计数}void PCA_Intrrpt(void) interrupt 7{if(CCF0) CCF0=0;if(CCF1) CCF1=0; //软件清零if(CF) CF=0; //软件清零}。