原创 电位器控制三色LED单片机PWM驱动的简单程序

2015-9-22 19:09 2728 18 18 分类: MCU/ 嵌入式

朋友问能否用模拟量控制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--);
    }
}
 
 
img_1714.jpg

文章评论0条评论)

登录后参与讨论
我要评论
0
18
关闭 站长推荐上一条 /2 下一条