我用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--);
  }
}
