基于STC8G1K08A的可调节占空比和频率的PWM应用案例

CSDN的小白分享

前言

学习单片机以来,都是写了就算的态度。总结的话用TXT和WPS文档老是容易忘掉放在了哪里。而且排版也不好看,无意间发现了可以在这里面做记录,于是就开始了啦!

由于工程需要(三色灯切换同时呼吸效果),最近在研究一款比较合适用来做面板LED控制的小成本芯片:以下就是STC8G1K08A系列的开发记录,实现了可调频调占空比的PWM输出。

一、STC8G系列的介绍

STC8G是STC公司最近新出的一款产品,它性价比高,内存充足等特点,主要是价格适合,功能足,可以满足各种扩展需要。至于其他内容可以上官网自己查看,不然就有卖广告的嫌疑了~

二、使用记录

1.建立工程

本人是在KEIL中进行开发的,所以使用前需要先在STC官网下载以下它的最新ISP软件,然后在软件把最新的STC8G系列的头文件加到KEIL的INC文件夹中。

按下该按钮后选择安装KEIL的目即可

2.打开工程所需的芯片功能,及本人的函数

1.主程序中断函数如下:

//定时器0中断----------------------------------------------------------------------------------------
void Time0() interrupt 1
{
    WDT_CONTR=0x30;
    Time_Cnt();
}
void main()
{
    Port_Init();
    EA  = 0;
    Delay_Us(1);
    Delay_N_Ms(1);
    Timer0_Init();
    Delay_N_Ms(10);
    PWM_Init();
    PWM_Off();
    Delay_N_Ms(10);
    Data_Init();
    EA  = 1;
    while(1)
    {
			  On_Off_Chk();
              Led_Control();
    }
}

2.初始化函数:

void Port_Init(void)//根据芯片引脚定义,把PWM的输出脚定义为推挽输出
{       

    P3M1 = 0xF3;//1111 0011
    P3M0 = 0x0C;//0000 1100  
    P5M1 = 0xEF;//1110 1111
    P5M0 = 0x10;//0001 0000
}
//定时器0初始化--------------------------------------------------------------------------------------
void Timer0_Init(void)	
{
		AUXR |= 0x80;		//定时器时钟1T模式
		TMOD &= 0xF0;		//设置定时器模式
		TL0 = 0x20;		//设置定时初值
		TH0 = 0xD1;		//设置定时初值
		TF0 = 0;		//清除TF0标志
		TR0 = 1;		//定时器0开始计时
    ET0 = 1;		    //使能定时器0中断
    PT0 = 0;		    //定时器0优先级置低
}	
void PWM_Init(void)
{
    CCON = 0x00;
    CMOD = 0x08;     //PCA时钟为系统时钟
    CL = 0x00;       //PCA计数器初始值低8位
    CH = 0x00;       //PCA计数器初始值高8位

    CCAPM0 = 0x42;                              //PCA模块1为PWM工作模式
    PCA_PWM0 = 0xc0;                            //PCA模块1输出10位PWM
    CCAP0L = 0x00;
    CCAP0H = 0x00;
	
	  CCAPM1 = 0x42;                              //PCA模块1为PWM工作模式
    PCA_PWM1 = 0xc0;                            //PCA模块1输出10位PWM
    CCAP1L = 0x00;
    CCAP1H = 0x00;
	
	  CCAPM2 = 0x42;                              //PCA模块1为PWM工作模式
    PCA_PWM2 = 0xc0;                            //PCA模块1输出10位PWM
    CCAP2L = 0x00;
    CCAP2H = 0x00;
    CR = 1;                                     //启动PCA计时器
}
void Data_Init(void)
{
    setPWM = 1023;
    chaSynFlag = 0;
    ledUpdateColorFlag = 0;
    ledKeepOffFlag = 0;
    pwmUpdateFlag = 0;
	  switchOnFlag = 0;
    countBreNMs = 0;
    countOffNMs = 0;
}

3.为了简化输出和方便以后修改做的自定义函数封装:

void Time_Cnt(void)//程序主要时间逻辑计算函数
{
    countBreNMs++;
    if(countBreNMs >= PWM_BREATHE_NS)
    {
        pwmUpdateFlag = 1;
        countBreNMs = 0;
    }
    count20Ms++;
    if(count20Ms >= 10)
    {
        count20Ms = 0;
        count1S++;
        if(count1S >= 200)
        {
            count1S = 0;
            countOffNMs ++;
            countHoldNMs++;
            if(countOffNMs >= PWM_OFF_TIME)
            {
                countOffNMs = 0;
                ledKeepOffFlag = 0;
            }
            else if(countHoldNMs >= PWM_HOLD_TIME)
            {
                countHoldNMs = 0;
                ledKeepHoldFlag = 0;
            }
        }
    }
}
void PWM_Output_Capp0(void)
{
    PCA_PWM0=0x30&(setPWM>>4)|0xc0;//高两位XCCAPnH[1:0]
    CCAP0H = setPWM;//低8位CCAPnH[7:0]
}

void PWM_Output_Capp1(void)
{
    PCA_PWM1=0x30&(setPWM>>4)|0xc0;//高两位XCCAPnH[1:0]
    CCAP1H = setPWM;//低8位CCAPnH[7:0]
}

void PWM_Output_Capp2(void)
{
    PCA_PWM2=0x30&(setPWM>>4)|0xc0;//高两位XCCAPnH[1:0]
    CCAP2H = setPWM;//低8位CCAPnH[7:0]
}

void PWM_Off(void)
{
    PCA_PWM0|=0x3F;//高两位XCCAPnH[1:0]
    CCAP0H = 0XFF;//低8位CCAPnH[7:0]
	
	  PCA_PWM1|=0x3F;//高两位XCCAPnH[1:0]
    CCAP1H = 0XFF;//低8位CCAPnH[7:0]
	
	  PCA_PWM2|=0x3F;//高两位XCCAPnH[1:0]
    CCAP2H = 0XFF;//低8位CCAPnH[7:0]
}

void PWM_On(void)
{
		if(chaSynFlag)
		{
				if(!ledKeepHoldFlag)
				{
						setPWM ++;
						if(setPWM == 1023)
						{
								chaSynFlag = 0;
								ledUpdateColorFlag = 1;
								ledKeepOffFlag = 1;					
						}	
				}				
		}
		else
		{
				setPWM --;
				if(setPWM == 0)
				{
						chaSynFlag = 1;
            ledKeepHoldFlag = 1;
            countHoldNMs = 0;				
				}	
		}
		Led_Select();
}

void Led_Control(void)
{
		if((!ledKeepOffFlag)&&(switchOnFlag))
		{
			if(pwmUpdateFlag)
			{
					PWM_On();
					pwmUpdateFlag = 0;	
					countOffNMs = 0;	
			}
		}
		else
		{
			PWM_Off();
			countBreNMs = 0;
		}
}

void On_Off_Chk(void)
{
	if(!ON_OFF_SW)
	  switchOnFlag = 1;
	else
	{
		setPWM = 1023;
    chaSynFlag = 0;
    ledUpdateColorFlag = 0;
    ledKeepOffFlag = 0;
    pwmUpdateFlag = 0;
	  switchOnFlag = 0;
    countBreNMs = 0;
    countOffNMs = 0;
		switchOnFlag = 0;
	}
}

void Led_Select(void)
{
		if(ledUpdateColorFlag)
		{
			ledUpdateColorFlag = 0;
			ledSelectCnt ++;
			if(ledSelectCnt >= 35)
			{
				ledSelectCnt = 0;
			}
			ledSrlectData = ledBuf[ledSelectCnt];
		}
	
		if(ledSrlectData == 0)
		  PWM_Output_Capp0();
		else if(ledSrlectData ==1)
		  PWM_Output_Capp1();
		else if(ledSrlectData == 2)
		  PWM_Output_Capp2();
		else if(ledSrlectData == 3)
		{
			PWM_Output_Capp0();
			PWM_Output_Capp1();
		}
		else if(ledSrlectData == 4)
		{
			PWM_Output_Capp1();
			PWM_Output_Capp2();
		}
		else if(ledSrlectData == 5)
		{
			PWM_Output_Capp0();
			PWM_Output_Capp2();
		}
		else if(ledSrlectData == 6)
		{
			PWM_Output_Capp0();
			PWM_Output_Capp1();
			PWM_Output_Capp2();
		}		
}

4.在头文件中进行变量定义和宏定义即可方便的调节呼吸和变色效果:

sbit    ON_OFF_SW 	= P5^5;
#define MAIN_Fosc       24000000L   //定义主时钟
#define PWM_BREATHE_NS   5   //一次呼吸的时间
#define PWM_OFF_TIME     3   //每次停顿的时间
#define PWM_HOLD_TIME    3   //最亮停顿的时间
//screen
bit ledUpdateColorFlag=0;
bit ledKeepHoldFlag=0;
bit ledKeepOffFlag=0;
bit pwmUpdateFlag=0;
bit switchOnFlag=0;
bit chaSynFlag = 0;
u8  ledSrlectData=0;
u8  ledSelectCnt=0;
u16 setPWM=0;//10位占空比预存变量0-1023
u8 code ledBuf[35] = 
{
	0,1,2,3,4,5,6,
	4,3,1,5,0,6,2,
	1,2,4,6,5,0,3,
	6,5,4,3,2,1,0,
	4,3,2,6,2,0,1
};//添加该数组目的是让灯的颜色变的随机(伪随机),可以适当的增加但同时对应的选择变量也要更改条件

//Timer
u8	countBreNMs;
u8	countOffNMs;
u8	countHoldNMs;
u8	count20Ms;
u8	count1S;

总结

以上是这次工程的全部函数代码,至于一些基本的头文件这里就不一一的细讲了。工程实现了可调节呼吸频率,呼吸时间的三色灯。
小白一个,期待各位大佬多多指教。同时也希望自己能保持每个工程都编写文章以做记录和反省!

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值