STC12系列单片机的PWM输出汇编语言示例程序
STC12C5A60S2单片机PWM程序
STC12C5A60S2PWM程序
由于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; //禁止寄存器CCON中CF位的中断)
CL=0; //PCA的16位计数器低八位
CH=0; //PCA的16位计数器高八位
CMOD=0x00; //选择系统时钟/12 为计数脉冲,则PWM的频率f=sysclk/256/12;
CCAP0H=0x80; // 占空比控制
CCAP0L=0x80;
PCA_PWM0=0x00; //控制占空比的第九位为0
CCAPM0=0x42; //允许P13作为PWM输出
CR=1; //启动PCA计数器
while(1)
{
if(P10==0)
{
delay(200);
while(P10==0);
CCAP0H+=10; //占空比调节
CCAP0L+=10;
}
}
}
欢迎阅读。
基于STC12单片机做的PWM控制直流电机和角度传感器程序
s SCLK = P2 ^ 5;//时钟
sbit k1=P3^4;
sbit k2=P3^5;
//Function Definition函数声明
void Lcd_init(void);
#include <math.h> //Keil library
#include <stdio.h> //Keil library
//#define FOSC 18432000L
#define FOSC 11059200L //晶振11.0592M
#define BAUD 9600
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define uchar unsigned char
#define uint unsigned int
/*Declare SFR associated with the ADC */
/*sfr AUXR1 = 0XA2;
sfr ADC_CONTR = 0xBC; //ADC control register
void LCD_Write_string(unsigned char X,unsigned char Y,unsigned char *s);
void LCD_Write_number(unsigned char s);
void Lcd_Mark2(void);
void Conut(void);
void delayms(unsigned int ms);
#define ADC_SPEEDLL 0x00 //420 clocks
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。
STC12内部PWM使用方法解析
STC12内部PWM使用方法解析首先说一下PWM是一个什么样的东西,PWM的中文名字叫做“脉宽调制”,也就是说呢,我们的电路有两种状态,通或者不通,我们用单片机控制输出高电平低电平从而控制电路的通断来达到我们想要的某种模拟电路特有的效果的一种技术。
我们举个例子,比如说我们的直流电机直接接在五伏的电源上,要么全速运转,要么不转。
那我们怎样实现调速呢?我们可以通过单片机来控制这个电路,让电机电路通一段时间断一段时间。
比如说通一秒断一秒,那么电机的速度就会比全速运转时候低,不断改变这个通断之间的间隔时间,我们就可以达到一种调速的效果。
下面呢,我们就切入正题。
STC12C5A60S2这款单片机(下面说成12系列单片机),与89系列的单片机相比,它的内部增加了独立的PCA(计数器阵列,说简单点就是好几个计数器)或者说PWM模块,通过配置相关的特殊功能寄存器,我们可以实现一些额外的功能,比如说计时器,高脉冲输出,PWM输出等,如果我们用这种方法来实现PWM功能,要比用定时器加中断组合那种方法简单很多。
大家可能都看过那个技术文档,但是不得不说它的技术文档写的真是让人不敢恭维。
经过查阅资料,还有逛论坛,我大致了解了PCA模块,它到底是什么样一个东西,应当怎样用等。
下面我把相关的内容分享给大家,与大家交流一下。
如果有什么不对的地方,大家可以评论里边指出来,一定虚心思考。
我们看官方对PCA模块的介绍:对于图片里边提到的定时器的概念,大家已经非常熟悉了,而“捕获/比较器”,这个东西对我们来说可能比较生疏,其实通俗的说呢,在PWM功能里边,模块0与模块1里边的捕获比较器,就是一个比较大小的硬件装置。
假如有一个固定的值装在模块0的特殊功能寄存器里边,有一个外部来的外来值与它里边装的那个值不停的进行比较大小这种操作,如果外来的值比较小,那么这个比较大小的装置就会输出0,反之输出1。
(至于捕获模式,我们暂时用不到,他们其实是一个可以检测到相应引脚高低电平变化的硬件装置,我们知道,引脚拉高拉低并不是一下子就完成的,无论拉高或拉低,都有一定的上升或下降沿,捕获其实捕获的就是这种上升下降沿,一旦捕获到,可以触发相应的中断,这些都由软件决定。
STC12C5A32AD单片机PCA模块PWM
一、PCA.c
* 文 件 名:PCA.c * 芯 片:STC12C5A60S2 * 晶 振:12MHz * 创 建 者:冷月 * 创建日期:2010.8.18 * 修改日期:2010.9.3 修改设置波特率参数为x%,增加定时器0作 为PCA时钟源 * 功能描述:2路PCA的捕获、高速输出、16bit定时器、PWM实现 */ #include <STC12C5A.H> #include "PCA.h" #define uchar unsigned char #define uint unsigned int static uint step0 = 0; static uint step1 = 0; void PCA_Init(bit module, uchar PCA_CCAPMn, uchar PCA_CCAPnH, uchar PCA_CCAPnL, uchar PCACLK) { CMOD = 0x80 | PCACLK; //空闲模式下PCA停止工作,PCA/PWM时 钟源输入 CCON = 0x00; if (module == 0) //PCA模块0 { CCAPM0 = PCA_CCAPMn; CCAP0L = PCA_CCAPnL; CCAP0H = PCA_CCAPnH; step0 = ((PCA_CCAPnH & 0x00FF)<<8) | PCA_CCAPnL; } else //PCA模块1 { CCAPM1 = PCA_CCAPMn; CCAP1L = PCA_CCAPnL;
//启动PCA计数器计数
void Set_PWM_Fre(uint fre) { float timerVal; //定时器定时时间 uchar tempTimerVal; timerVal = 1000000.0 / 256 / fre; tempTimerVal = (uint)(65536 - timerVal*12) % 256; TH0 = tempTimerVal; TL0 = tempTimerVal; } /* * 函 数 名:Set_PWM0 * 功能描述:设置PWM0占空比 * 输入参数:duty:占空比0~100 * 返 回 值:无 */ void Set_PWM0(uchar duty) { uchar temp; if (duty == 0) //PWM固定输出低 { PCA_PWM0 = 0x03; //PWM模式下,CCAPnL,CCAPnH第九位 temp = 0xFF; } else if (duty == 100) //PWM固定输出高 { PCA_PWM0 = 0x00; //PWM模式下,CCAPnL,CCAPnH第九位 temp = 0; } else { PCA_PWM0 = 0x00; temp = 256 - 256*duty/100;
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单片机spwm发生程序带仿真文件
pr&rb=0&rs=1&seller_id=1&sid=289b43264a7d3525&ssp2=1&stid=0&t=tpclicked
3_hc&tu=u1831118&u=http%3A%2F%2Fwww%2E51hei%2Ecom%2Fmcபைடு நூலகம்%2F211
stc12c5a60s2单片机spwm发生程序带仿真文件
包含文件和仿真文件的下载地址:51hei/f/stc12c5a60s2_spwm.zip下面是主程
序部分:#include #include
#define uintunsigned int
uchar index;uchara;void init_pca(void)//pca计数器初始化函数
8%2Ehtml&urlid=0”id=“5_nwl”mpid=“5”target=“_blank”>pca计数器
}
void init_timer(void)//计数器初始化函数
{
TMOD= 0x12; //计数器0工作在方式模式2,计数器1工作在方式1
TH0 = 0xFF;//T0的计数值为5,把时钟源5分频
{
CMOD=0x04;//计数器0的溢出为PCA计数器的时钟源
CCON=0x00;
CCAPM0=0x42;//8位PWM输出,无中断
CL=0x00;//清零pca计数器
CH=0x00;
CCAP0L=pwm[0];//初始化spwm输出的占空比
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应用
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:允许比较器功能控制位。
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
单片机输出PWM温控程序C语言代码
单片机PWM温控C语言程序部分代码#include <reg52.h>#include <at89x52.h>#include <keyscan.h>extern void scan_full(void);extern unsigned char key_scan(void);extern bit key_ok;unsigned char pwm_set,key_value;unsigned char count;sbit PWM=P3^6; //将PWM定义为P3口的第六位?bit up,down,set_flag;unsigned char code BCD[]={0x3f,0x06,0x5b,0x4f, //此处是将0-F转换成0x66,0x6d,0x7d,0x07, //相应的BCD码0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay1(unsigned char t){while(t--);}void pwm(void) interrupt 5//定时器2产生PWM波形{TF2=0; //定时器2的溢出标志要软件清除,//但当RCLK或TCLK为1时由硬件清除if((count>=pwm_set)&amt;&amt;(count<10))PWM=1;elsePWM=0;count++;if(count==10)count=0x00;}void key_pwm(unsigned char x)//把键值转化为PWM设置值{switch(x) //把矩阵键盘转化为独立键盘{case 1:up=1;break;case 2:down=1;break;case 3:set_flag=!set_flag;break;default:break;}//设置PWM参数:pwm_setif(up&amt;&amt;set_flag){pwm_set++;up=0;if(pwm_set>=10)pwm_set=0x00;}if(down&amt;&amt;set_flag){pwm_set--;down=0;if(pwm_set==0xff) //减到-1?pwm_set=9;}if(!set_flag){up=0;down=0;}}void main(void){TH2=0xb1; //定时20MSTL2=0xe0;RCAP2H=0xb1;//定时器2溢出会把该单元内容送到TH2和TL2 RCAP2L=0xe0;EA=1;ET2=1;TR2=1;while(1){scan_full(); //看是否有键按下if(key_ok) //有键按下,则判断到底是哪个键按下{key_value=key_scan();//键值送key_value暂存P0=~BCD[key_value]; /*此三句是将键值显示出来*/P2=0xfe;delay1(200);key_pwm(key_value); //调用键值转PWM设置参数函数key_value=0x00; //清除键值,以免一次按下,多次响应}P0=~BCD[pwm_set]; /***此三句是将pwm_set值显示出来*/P2=0xfd;delay1(200);}}#include <reg52.h>//#include <at89x52.h>//unsigned char code BCD[]={0x3f,0x06,0x5b,0x4f, //此处是将0-F转换成//相应的BCD码 :// 0x66,0x6d,0x7d,0x07,// 0x7f,0x6f,0x77,0x7c,// 0x39,0x5e,0x79,0x71};//unsigned char code KEY[]={0x00,0x00,0x01,0x02,0x03,//此处是为使程序通用,当键值不是按// 0x04,0x05,0x06,0x07,//这个排列时,把此表更改即可// 0x08,0x09,0x0a,0x0b,//最前面的那个0x00是为了查表方便,// 0x0c,0x0d,0x0e,0x0f};//因为键值是从1开始的sfr key_port=0x90; //定义P1口为键盘扫描口bit key_ok=0; //有键按下的标志/*************延时子程序*****************调用一次用时18微秒,t每加1,用时增加6微秒*/void delay(unsigned char t){while(t--);}unsigned char r_left(unsigned char x)//循环左移一位{x<<=1;x++;return(x);}/*************粗判有无键按下**************有键按下则将key_ok置1************/void scan_full(void){unsigned char temp;key_port=0xf0; //低半字节为行线,高半字节为列线temp=P1;if(temp!=0xf0)key_ok=1;elsekey_ok=0;}/************键盘扫描程序*****************************功能:返回键值,当无键按下时,返回0*************/unsigned char key_scan(void){unsigned char temp,count=0x01,key_value;//按键返回值unsigned char x_scan=0xfe,y_scan=0xef;//行、列扫描码unsigned char i,j,y; //行数和列数while(1){scan_full(); //粗判是否有键按下if(key_ok==1){key_ok=0;delay(200); //延时去抖动scan_full(); //再次粗判是否有键按下if(key_ok==1){for(i=0;i<4;i++) //扫描4行{key_port=x_scan;for(j=0;j<4;j++) //每行4列{temp=key_port;temp=temp&amt;0xf0;y=y_scan&amt;0xf0;if(temp==y){while(key_ok!=0)//等待按键松开{scan_full();}key_value=count;return(key_value);//找到键值,马上返回}else{count++;y_scan=r_left(y_scan);}}y_scan=0xef; //扫描完一列,重新对列扫描量赋初值x_scan=r_left(x_scan);//行扫描码左移一位,扫描下一行}}}return(key_value);//没键按下,返回0}}//unsigned char key(void)//{// unsigned char x;// unsigned char y;// x=key_scan();// return(x);// y=KEY[x];// return y;//}。