热度 18
2015-9-22 19:09
2768 次阅读|
0 个评论
朋友问能否用模拟量控制PWM,这么简单当然easy了,我用STC15W408AS的DIP20脚的单片机,因为这种单片机具有AD输入通道和PWM输出,很快做好了一个单通道的实验,完事想这个单片机有三个PWM输出,我可以驱动三色LED进行显示玩玩,用三个电位器控制三色LED的亮度变化就可以输出各种颜色了: 硬件很简单,就是三个10K电位器对电源5V分压,调整端电压进三个AD:P1.0,1.1,1.2,PWM输出在P3.5,3.6,3.7,三色LED红蓝绿正极接一起接5V正极,三个LED负极分别接1K电阻进三个PWM输出,调整电位器分别控制PWM输出驱动LED亮度变化,不同组合就是不同颜色。 C程序如下,大部分摘录自STC的下载工具里面的范例,大部分选项参数并没有清理,原汁原味,当然也有一点错误给予修正: //STC15W408AS DIP20 11.0592MHz 串口115.2K比特率 //本程序电位器输入三个模拟量,AD结果送串口,同时输出三个PWM驱动三基色LED //PWM移动到第二输出口,以便让开AD三个输入通道 //PWM设定为8bit输出,AD只取高八位,刚好对应 #include "reg51.h" #include "intrins.h" #define FOSC 11059200L #define BAUD 115200 typedef unsigned char BYTE; typedef unsigned int WORD; #define URMD 0 //0:使用定时器2作为波特率发生器 //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器 //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器 sfr T2H = 0xd6; //定时器2高8位 sfr T2L = 0xd7; //定时器2低8位 sfr AUXR = 0x8e; //辅助寄存器 sfr ADC_CONTR = 0xBC; //ADC控制寄存器 sfr ADC_RES = 0xBD; //ADC高8位结果 sfr ADC_LOW2 = 0xBE; //ADC低2位结果 sfr P1ASF = 0x9D; //P1口第2功能控制寄存器 #define ADC_POWER 0x80 //ADC电源控制位 #define ADC_FLAG 0x10 //ADC完成标志 #define ADC_START 0x08 //ADC起始控制位 #define ADC_SPEEDLL 0x00 //540个时钟 #define ADC_SPEEDL 0x20 //360个时钟 #define ADC_SPEEDH 0x40 //180个时钟 #define ADC_SPEEDHH 0x60 //90个时钟 sfr P_SW1 = 0xA2; //外设功能切换寄存器1 #define CCP_S0 0x10 //P_SW1.4 #define CCP_S1 0x20 //P_SW1.5 sfr CCON = 0xD8; //PCA控制寄存器 sbit CCF0 = CCON^0; //PCA模块0中断标志 sbit CCF1 = CCON^1; //PCA模块1中断标志 sbit CR = CCON^6; //PCA定时器运行控制位 sbit CF = CCON^7; //PCA定时器溢出标志 sfr CMOD = 0xD9; //PCA模式寄存器 sfr CL = 0xE9; //PCA定时器低字节 sfr CH = 0xF9; //PCA定时器高字节 sfr CCAPM0 = 0xDA; //PCA模块0模式寄存器 sfr CCAP0L = 0xEA; //PCA模块0捕获寄存器 LOW sfr CCAP0H = 0xFA; //PCA模块0捕获寄存器 HIGH sfr CCAPM1 = 0xDB; //PCA模块1模式寄存器 sfr CCAP1L = 0xEB; //PCA模块1捕获寄存器 LOW sfr CCAP1H = 0xFB; //PCA模块1捕获寄存器 HIGH sfr CCAPM2 = 0xDC; //PCA模块2模式寄存器 sfr CCAP2L = 0xEC; //PCA模块2捕获寄存器 LOW sfr CCAP2H = 0xFC; //PCA模块2捕获寄存器 HIGH sfr PCA_PWM0 = 0xf2; //PCA模块0的PWM寄存器 sfr PCA_PWM1 = 0xf3; //PCA模块1的PWM寄存器 sfr PCA_PWM2 = 0xf4; //PCA模块2的PWM寄存器 void InitUart(); void InitADC(); void SendData(BYTE dat); BYTE GetADCResult(BYTE ch); void Delay(WORD n); void ShowResult(BYTE ch); void main() { // ACC = P_SW1; // ACC = ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=0 // P_SW1 = ACC; //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2) ACC = P_SW1; ACC = ~(CCP_S0 | CCP_S1); //CCP_S0=1 CCP_S1=0 ACC |= CCP_S0; //(P3.4/ECI_2, P3.5/CCP0_2, P3.6/CCP1_2, P3.7/CCP2_2) P_SW1 = ACC; // // ACC = P_SW1; // ACC = ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=1 // ACC |= CCP_S1; //(P2.4/ECI_3, P2.5/CCP0_3, P2.6/CCP1_3, P2.7/CCP2_3) // P_SW1 = ACC; CCON = 0; //初始化PCA控制寄存器 //PCA定时器停止 //清除CF标志 //清除模块中断标志 CL = 0; //复位PCA寄存器 CH = 0; CMOD = 0x02; //设置PCA时钟源 //禁止PCA定时器溢出中断 PCA_PWM0 = 0x00; //PCA模块0工作于8位PWM CCAPM0 = 0x42; //PCA模块0为8位PWM模式 CCAP0H = CCAP0L = 0x00; //PWM0的占空比初值 PCA_PWM1 = 0x00; //PCA模块1工作于8位PWM CCAPM1 = 0x42; //PCA模块1为8位PWM模式 CCAP1H = CCAP2L = 0x00; //PWM1的占空比初值 PCA_PWM2 = 0x00; //PCA模块2工作于8位PWM CCAPM2 = 0x42; //PCA模块2为8位PWM模式 CCAP2H = CCAP2L = 0x00; //PWM2的占空比初值 CR = 1; //PCA定时器开始工作 InitUart(); //初始化串口 InitADC(); //初始化ADC while (1) { ShowResult(0); //显示通道0 CCAP0H = CCAP0L = GetADCResult(0);//PWM0输出AD0通道的值 ShowResult(1); //显示通道1 CCAP1H = CCAP1L = GetADCResult(1);//PWM1输出AD1通道的值 ShowResult(2); //显示通道2 CCAP2H = CCAP2L = GetADCResult(2);//PWM2输出AD2通道的值 // ShowResult(3); //显示通道3 // ShowResult(4); //显示通道4 // ShowResult(5); //显示通道5 // ShowResult(6); //显示通道6 // ShowResult(7); //显示通道7 // Delay(10); } } /*---------------------------- 发送ADC结果到PC ----------------------------*/ void ShowResult(BYTE ch) { SendData(ch); //显示通道号 SendData(GetADCResult(ch)); //显示ADC高8位结果 // SendData(ADC_LOW2); //显示低2位结果 // Delay(20); } /*---------------------------- 读取ADC结果 ----------------------------*/ BYTE GetADCResult(BYTE ch) { ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START; _nop_(); //等待4个NOP _nop_(); _nop_(); _nop_(); while (!(ADC_CONTR ADC_FLAG));//等待ADC转换完成 ADC_CONTR = ~ADC_FLAG; //Close ADC return ADC_RES; //返回ADC结果 } /*---------------------------- 初始化串口 ----------------------------*/ void InitUart() { SCON = 0x5a; //设置串口为8位可变波特率 #if URMD == 0 T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值 T2H = (65536 - (FOSC/4/BAUD))8; AUXR = 0x14; //T2为1T模式, 并启动定时器2 AUXR |= 0x01; //选择定时器2为串口1的波特率发生器 #elif URMD == 1 AUXR = 0x40; //定时器1为1T模式 TMOD = 0x00; //定时器1为模式0(16位自动重载) TL1 = 0xd8; //设置波特率重装值 TH1 = 0xff; //115200 bps(65536-18432000/4/115200) TR1 = 1; //定时器1开始启动 #else TMOD = 0x20; //设置定时器1为8位自动重装载模式 AUXR = 0x40; //定时器1为1T模式 TH1 = TL1 = 0xfb; //115200 bps(256 - 18432000/32/115200) TR1 = 1; #endif } /*---------------------------- 初始化ADC ----------------------------*/ void InitADC() { P1ASF = 0xff; //设置P1口为AD口 ADC_RES = 0; //清除结果寄存器 ADC_CONTR = ADC_POWER | ADC_SPEEDLL; Delay(2); //ADC上电并延时 } /*---------------------------- 发送串口数据 ----------------------------*/ void SendData(BYTE dat) { while (!TI); //等待前一个数据发送完成 TI = 0; //清除发送标志 SBUF = dat; //发送当前数据 } /*---------------------------- 软件延时 ----------------------------*/ void Delay(WORD n) { WORD x; while (n--) { x = 5000; while (x--); } }