打印

提问,关于stc89c52单片机PWM输出的问题

[复制链接]
2019|18
手机看帖
扫描二维码
随时随地手机跟帖
沙发
289951099|  楼主 | 2016-7-6 18:57 | 只看该作者
                                          
/*串口接收*/

#include<reg52.h>
sbit led1=P1^0;
sbit led2=P1^1;  
sbit led3=P1^2;  
sbit led4=P1^3;     


static unsigned char  dat,countT0;


void delay(int t)
{
    char i;
    while(t--)
    {
        for(i=0;i<100;i++);
    }
}         

void timerinit()
{   
    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率   
    //TMOD &= 0x0F;        //清除定时器1模式位
    TMOD = 0x22;        //设定定时器1、定时器0为8位自动重装方式
    TL1 = 0xe8;        //设定定时初值       //1200
    TH1 = 0xe8;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
       
        ET0 = 1;                        //允许定时器0中断
        TR0 = 1;                        //timer0   start
    TL0 = 0xe8;        //设定定时0初值       //0.1ms
    TH0 = 0xe8;        //设定定时器0重装值
    ES=1;
    EA=1;
}


void qianjing()
{
        if(countT0<50)
        {
                led1=0;
        }
        if(countT0>50)
        {
                led1=1;
        }                           
}

void houtui()
{
        if(countT0<50)
        {
                led2=0;
        }
        if(countT0>50)
        {
                led2=1;
        }                  
}

void left()
{
        if(countT0<50)
        {
                led3=0;
        }
        if(countT0>50)
        {
                led3=1;
        }                  
}
void right()
{
        if(countT0<50)
        {
                led4=0;
        }
        if(countT0>50)
        {
                led4=1;
        }                  
}

void jieshou()
{
        switch(dat)
        {
                 case 0xaa:qianjing();break;//如果串口接收的为0xaa ,则P1.0口输出PWM
                 case 0x77:houtui();break;//如果串口接收的为0x77 ,则P1.1口输出PWM
                 case 0xa7:left(); break;//如果串口接收的为0xa7 ,则P1.2口输出PWM
                 case 0x7a:right();break;//如果串口接收的为0x7a ,则P1.3口输出PWM
        //         case 0xa0:P1=0xe0;break;
        //        default:P1=0xff;break;
        }
}


void main()
{
        dat=0x00;
    timerinit();

        delay(1);

    while(1)
    {       
                jieshou();                  
    }
}
/*串口接收*/
void uart() interrupt 4
{
    if(RI)                               //接收中断
    {   
        RI=0;                           //读取接受到的数据
        dat=SBUF;
    }                             
}

void timer0() interrupt 1
{  

   // TL0 = 0x9c;        //设定定时0初值       //0.1ms
   // TH0 = 0x9c;        //设定定时器0重装值

                countT0++;
                if(countT0==100)countT0=0;
               
               
                        
}

使用特权

评论回复
板凳
289951099|  楼主 | 2016-7-6 19:03 | 只看该作者
但是实测PWM输出有不定时的断续现象

使用特权

评论回复
地板
289951099|  楼主 | 2016-7-6 19:06 | 只看该作者


图片引用地址。
请问是什么原因引起的。谢谢。

使用特权

评论回复
5
289951099|  楼主 | 2016-7-6 20:44 | 只看该作者
会不会是误码引起的?误码怎么处理呢?

使用特权

评论回复
6
chunyang| | 2016-7-6 20:46 | 只看该作者
应该是你的程序结构问题,仔细检查吧。

使用特权

评论回复
7
289951099|  楼主 | 2016-7-6 21:10 | 只看该作者
由于串口是用433M无线传输的,是信号误码原因引起的,问题已确定,但是这个误码怎么处理呢?

使用特权

评论回复
8
289951099|  楼主 | 2016-7-6 21:14 | 只看该作者
误码处理,在传输固定数据的时候,可用查表法处理。
但是在传输不确定的数据情况下怎么处理误码呢?
在线等。

使用特权

评论回复
9
chunyang| | 2016-7-6 21:26 | 只看该作者
通常无线传输是靠协议和校验来保证数据正确性的,高要求下可以使用纠错编码来恢复部分有错的数据。不过,楼主的应用是根据无线传输的数据来决定PWM输出,那将是实时的,纠错算法需占用大量带宽,楼主所用信道未必能很好的支持,所以还是用校验吧,发现有错则维持上一帧数据不变,这虽然不真实,但总比误码好。

使用特权

评论回复
10
289951099|  楼主 | 2016-7-6 22:30 | 只看该作者
                                          
/*串口接收*/

#include<reg52.h>
sbit led1=P1^0;
sbit led2=P1^1;  
sbit led3=P1^2;  
sbit led4=P1^3;     


static unsigned char dat,dat0,countT0;


void delay(int t)
{
    unsigned int i;
    while(t--)
    {
        for(i=0;i<100;i++);
    }
}         

void timerinit()
{   
    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率   
    //TMOD &= 0x0F;        //清除定时器1模式位
    TMOD = 0x22;        //设定定时器1、定时器0为8位自动重装方式
    TL1 = 0xe8;        //设定定时初值       //1200
    TH1 = 0xe8;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
       
        ET0 = 1;                        //允许定时器0中断
        TR0 = 1;                        //timer0   start
    TL0 = 0xe8;        //设定定时0初值       //0.1ms
    TH0 = 0xe8;        //设定定时器0重装值
    ES=1;
    EA=1;
}


void qianjing()
{         
        if(countT0<50)
        {
                led1=0;
        }
        if(countT0>50)
        {
                led1=1;
        }                           
}

void houtui()
{
        if(countT0<50)
        {
                led2=0;
        }
        if(countT0>50)
        {
                led2=1;
        }                  
}

void left()
{
        led3=1;                 
}
void right()
{
        led4=1;                 
}

void jieshou()
{
        switch(dat)
        {
                 case 0xaa:qianjing();break;
                 case 0x77:houtui();break;
                 case 0x7a:left();break;
                 case 0xa7:right();break;
                default:P1=0x00;break;
        }
}


void main()
{                                                                  

        dat=0x00;
        P1=0xff;
    timerinit();

        delay(1);

    while(1)
    {       
                 jieshou();
    }
}
/*串口接收*/
void uart() interrupt 4
{                            
    if(RI)                               //接收中断
    {   
        dat0=SBUF;
        RI=0;                           //读取接受到的数据
    }         
        switch(dat0)
        {
                case 0xaa:dat=dat0;break;
                case 0x77:dat=dat0;break;
                case 0x7a:dat=dat0;break;
                case 0xa7:dat=dat0;break;
                case 0xa0:dat=dat0;break;
                default:P1=0x00;break;
        }                                                            
}

void timer0() interrupt 1
{  
                countT0++;
                if(countT0>99)countT0=0;                                   
}

使用特权

评论回复
11
289951099|  楼主 | 2016-7-6 22:33 | 只看该作者
chunyang 发表于 2016-7-6 21:26
通常无线传输是靠协议和校验来保证数据正确性的,高要求下可以使用纠错编码来恢复部分有错的数据。不过,楼 ...

我重新做了个,跟你说的有点类似,但不是用协议。而是维持上一帧数据不变。但是又有一个问题。
就是出现LED3的PWM输出不稳定,一直有断续的情况,而其他三个PWM输出都是稳定的。

程序如下。
                                          
/*串口接收*/

#include<reg52.h>
sbit led1=P1^0;
sbit led2=P1^1;  
sbit led3=P1^2;  
sbit led4=P1^3;     


static unsigned char dat,dat0,countT0;


void delay(int t)
{
    unsigned int i;
    while(t--)
    {
        for(i=0;i<100;i++);
    }
}         

void timerinit()
{   
    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率   
    //TMOD &= 0x0F;        //清除定时器1模式位
    TMOD = 0x22;        //设定定时器1、定时器0为8位自动重装方式
    TL1 = 0xe8;        //设定定时初值       //1200
    TH1 = 0xe8;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
       
        ET0 = 1;                        //允许定时器0中断
        TR0 = 1;                        //timer0   start
    TL0 = 0xe8;        //设定定时0初值       //0.1ms
    TH0 = 0xe8;        //设定定时器0重装值
    ES=1;
    EA=1;
}


void qianjing()
{         
        if(countT0<50)
        {
                led1=0;
        }
        if(countT0>50)
        {
                led1=1;
        }                           
}

void houtui()
{
        if(countT0<50)
        {
                led2=0;
        }
        if(countT0>50)
        {
                led2=1;
        }                  
}

void left()
{
        led3=1;                 
}
void right()
{
        led4=1;                 
}

void jieshou()
{
        switch(dat)
        {
                 case 0xaa:qianjing();break;
                 case 0x77:houtui();break;
                 case 0x7a:left();break;
                 case 0xa7:right();break;
                default:P1=0x00;break;
        }
}


void main()
{                                                                  

        dat=0x00;
        P1=0xff;
    timerinit();

        delay(1);

    while(1)
    {       
                 jieshou();
    }
}
/*串口接收*/
void uart() interrupt 4
{                            
    if(RI)                               //接收中断
    {   
        dat0=SBUF;
        RI=0;                           //读取接受到的数据
    }         
        switch(dat0)
        {
                case 0xaa:dat=dat0;break;
                case 0x77:dat=dat0;break;
                case 0x7a:dat=dat0;break;
                case 0xa7:dat=dat0;break;
                case 0xa0:dat=dat0;break;
                default:P1=0x00;break;
        }                                                            
}

void timer0() interrupt 1
{  
                countT0++;
                if(countT0>99)countT0=0;                                   
}

使用特权

评论回复
12
289951099|  楼主 | 2016-7-6 22:34 | 只看该作者
chunyang 发表于 2016-7-6 21:26
通常无线传输是靠协议和校验来保证数据正确性的,高要求下可以使用纠错编码来恢复部分有错的数据。不过,楼 ...

我用的是433M超再生无线通过串口传输数据。

使用特权

评论回复
13
289951099|  楼主 | 2016-7-6 23:39 | 只看该作者
chunyang 发表于 2016-7-6 21:26
通常无线传输是靠协议和校验来保证数据正确性的,高要求下可以使用纠错编码来恢复部分有错的数据。不过,楼 ...

刚才可能是什么地方的代码写错了。我重写了一次,那个有一个端口的PWM不正常现象消失了。

使用特权

评论回复
14
289951099|  楼主 | 2016-7-7 00:01 | 只看该作者
289951099 发表于 2016-7-6 23:39
刚才可能是什么地方的代码写错了。我重写了一次,那个有一个端口的PWM不正常现象消失了。 ...

还是不行。装上小电机,P1.2输出还是不正常,其他的都正常。不知道什么问题。

使用特权

评论回复
15
依依不舍| | 2016-7-7 09:19 | 只看该作者
是不是外围元件有问题,换片或上拉试试。

使用特权

评论回复
16
289951099|  楼主 | 2016-7-7 10:59 | 只看该作者
依依不舍 发表于 2016-7-7 09:19
是不是外围元件有问题,换片或上拉试试。

已更换过外围元件,也换过片,都不行。
如果只做三路PWM输出一切都正常。应该是软件时序上有问题。
但是还没有查出来具体 原因。
不能发图。

使用特权

评论回复
17
289951099|  楼主 | 2016-7-7 11:00 | 只看该作者
289951099 发表于 2016-7-7 10:59
已更换过外围元件,也换过片,都不行。
如果只做三路PWM输出一切都正常。应该是软件时序上有问题。
但是 ...

板上已做了上拉的。
就是有一路输出PWM会出现断续 的现象。而其他三路不会。

使用特权

评论回复
18
289951099|  楼主 | 2016-7-7 11:13 | 只看该作者
会不会是定时器的中断优先级与串口接收口中断优先级问题引起的呢?

使用特权

评论回复
19
chunyang| | 2016-7-16 00:51 | 只看该作者
端口少时正常,多了不正常,说明程序有误,特别要注意循环处理时的时间是否满足。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

15

帖子

0

粉丝