技术热线: 4007-888-234
设计开发

专注差异化嵌入式产品解决方案 给智能产品定制注入灵魂给予生命

开发工具

提供开发工具、应用测试 完善的开发代码案例库分享

技术支持

从全面的产品导入到强大技术支援服务 全程贴心伴随服务,创造无限潜能!

新品推广

提供新的芯片及解决方案,提升客户产品竞争力

新闻中心

提供最新的单片机资讯,行业消息以及公司新闻动态

软件产生PWM与按键实时处理-PICC初学例子

更新时间: 2019-03-23
阅读量:2387

十年专注单片机方案开发的方案公司英锐恩,分享软件产生PWM与按键实时处理-PICC初学例子。英锐恩现提供服务产品涉及主控芯片:8位单片机、16位单片机、32位单片机及各类运算放大器等。

假设现在有个产品,要实现一个按键调节LED的亮度(PWM六档调光)。要以最低成平,体积要小,抗干扰最好。用PIC12C508A,最适合不过了。

方案实现如下:

按键功能:
    一个普通的IO口接上拉电阻输入,通过按键拉地。按键低电平有效,高电平无效。
每按一下占空比增加一档。长按无效,第次增加一档。要防止干扰。

调光功能:
    一个普通的IO口外接三极管驱动LED,由于单片机没有PWM模块,没有中断功能。只能用软件产生PWM信号。 


   我们都知道用软件产生PMW 是占用单片机太多的时间,系统很难做其它工作。要如何实时处理按键功能,要多下
功夫才行。

编译软件为HI-PICC。

为了方面调试,先使用可擦写的PIC16F84A调试源程序,成功后再移值到PIC12C508A单片机系统。

《按键实时处理流程》 

声明申请两个标志  1,有效标志   2,完成标志  为静态私有,初始化只清零一次。

一,判断有效标志是否等于 1。是,向下执行。否,跳到二处。

    判断按键是否等于     0。是,向下执行。否,跳到三处。

    判断完成标志是否等于 0。是,向下执行。否,按键长按,无效退出。

    按键有效,增加占空比。完成标志置为 1。退出。

二,判断按键是否等于 0。是,置有效标志为 1。否,没有按键退出。

三,按键受干扰,或按键弹开。清所有标志,退出。

《软件产生PWM流程》 

一,根据占空比计算高电平延时,低电平延时。
    输出高电平,软件产生高电平延时。
    输出低电平,软件产生低电平延时。
二,循环执行约20毫秒,后退出。

《主程序主作流程》

一,调用初始化子程序.
二,调用按键处理子程序。
三,调用软件产生PWM子程序。
四,循环执行 二,三。


C源程序

/引入头文件*********************************************************
#include      

//脚位定义***********************************************************
#define       key       RA3                                //按键输入
#define       led       RB0                                //输出指示

//******************************************************************* 

//函数名称:port_init();
//输入参数:无
//输出参数:无
//功能描述:端口设置
//建造日期:2008.06.03
//*****************************************************************
void PortInit(void)
 {
     PORTA = 0xfd;                                         //  
     TRISA = 0xfd;                                         //A 口设置   
     
     PORTB = 0x00;                                         //
     TRISB = 0x00;                                         //B 口设置
 }
  

//*******************************************************************
//函数名称:KeyInt(*p);
//输入参数:占空比地址
//输出参数:无
//功能描述:按键处理函数
//建造日期:2008.06.03
//*******************************************************************
void KeyInt(unsigned char *p)
 {    
     static bit valid = 0;                                 //有效标志
     static bit finish = 0;                                //完成标志
     
     if (valid == 1)
      {
       if (key == 0)
        {
         if (finish == 0)
          {
           finish = 1;                                     //完成置位
           
           if (*p == 251)
            {
             *p = 0x01;                                    //按键有效 
            } 

 else
            {
             *p += 50;                                     //按键有效
            }
          }
        }
     
       else
        {
         valid = 0;                                        //有效清零
         finish = 0;                                       //完成清零 
        }   

 }
       
     else
      {
       if (key == 0) valid = 1;                            //有效置位
      } 
 }

//*******************************************************************
//函数名称:LedPwm(Pwm);
//输入参数:占空比
//输出参数:无
//功能描述:led 脉冲调宽输出
//建造日期:2008.06.03
//*******************************************************************
void LedPwm(unsigned char Pwm)
 {
     unsigned char PwmH;
     unsigned char PwmL;
     unsigned char i;
   
     
     for (i = 0; i < 20; i++)
      {
       PwmH = Pwm;                                         //脉冲高位
       PwmL = 255 - PwmH;                                  //脉冲低位

       led = 1;                                            // 
       while (PwmH--);                                     //高位输出 

 led = 0;                                            // 
       while (PwmL--);                                     //低位输出
      }        
 }

//*******************************************************************
//函数名称:main();
//输入参数:无
//输出参数:无
//功能描述:主要程序
//建造日期:2008.06.03
//*******************************************************************
void main(void)                                            // 

{   
     unsigned char Pwm = 0x01;                             //占空初值      

     PortInit();                                           //脚位设置
    
     while (1)
      {
       KeyInt(&Pwm);                                       //按键处理
       LedPwm(Pwm);                                        //脉冲输出
      }  
 } 

(文源网络,侵删)