51单片机如何扩展外部端口
 时间:2023-03-19来源:佚名
        | 
                我们知道 51单片机本身是没有pwm接口的,这个程序是通过软件模拟pwm.在一定的频率的方波中,调整高电平和低电平的占空比,即可实现LED灯亮度控制。  
          要用51产生PWM去控制LED,首先要确定PWM的周期T和占空比D,确定了这些以后,可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则D*T=n*t,类似的可以求出PWM低电平时间需要多少个时间基准n'。 
 
 /****************************************************************************************** 
 * 文件:PWM.c                                                                     
 * 备注:51单片机PWM完全注释                                          * 
 ******************************************************************************************/ 
#i nclude  
unsigned char CYCLE;                        /*PWM周期长度*/ 
unsigned char count = 0;             /*记录中断次数*/ 
unsigned char PWM_ON;                    /*PWM高电平时间计数*/ 
void delay()                                 /*延时约78ms*/ 
{ 
    unsigned char i, j;                      
    for(j = 100; j; j--)                  
        for(i = 255; i; i--) 
            ; 
} 
void main() 
{ 
    bit Flag;                                            /*变化状态标志,0:渐亮,1:渐暗*/ 
    TMOD = 0x01;                         /*时间基准为1ms*/ 
    TH0 = (65536 - 100) / 256;                /*右端表达式编译后为0xFF*/ 
    TL0 = (65536 - 100) % 256;              /*同上*/ 
    IE = 0x82;                                          /*开定时器0中断0x82 = 10000010*/ 
    TR0 = 1;                                  /*启动定时器0*/ 
    CYCLE = 10;                           /*十级亮度,即十级PWM*/ 
    while(!Flag)                                /*渐亮,每一次变化亮度增加1*/ 
    { 
        delay();                              /*延时*/ 
        PWM_ON  ;                                /*高电平脉宽延长,即亮度增加*/ 
        if(PWM_ON == CYCLE)               /*若高电平脉宽增长到整个周期*/ 
        { 
            Flag = 1;                                  /*则转为渐暗*/ 
        } 
    } 
    while(Flag)                                     /*渐暗,每一次变化亮度减少1*/ 
    { 
        delay();                                       /*延时*/ 
        PWM_ON--;                                /*高电平脉宽缩短,即亮度降低*/ 
        if(PWM_ON == 0)                       /*若高电平脉宽缩短到0*/ 
        { 
            Flag = 0;                                /*则转为渐亮*/ 
        } 
    } 
} 
void time0_server() interrupt 1 using 1 
{ 
    TH0 = (65536 - 100) / 256;            /*时间基准为1ms*/ 
    TL0 = (65536 - 100) % 256;          /*即每1ms触发一次中断*/ 
    if(count == PWM_ON)                    /*若中断次数达到亮度设定值*/ 
    {                                 
        P2 = 0xFF;                           /*则熄灯*/ 
    } 
    count  ;                                  /*每次中断记录 1*/ 
    if(count == CYCLE)                      /*若中断次数达到PWM周期长度*/ 
    { 
        count = 0;                              /*则清零中断记录*/ 
        if(PWM_ON != 0)                      /*若此时亮度值非零*/ 
        { 
            P2 = 0;                            /*则点灯*/ 
        } 
    } 
}  | 






