[STC单片机]

求助:STC8的PWM初始化后串口无法通讯

[复制链接]
5207|23
手机看帖
扫描二维码
随时随地手机跟帖
wfxsgsg|  楼主 | 2017-5-6 14:47 | 显示全部楼层 |阅读模式
我用的是STC8A8K64S4A12,在PWM输出后,想用串口通讯将PWM的占空比输出给电脑,可是经过排查,发现 P_SW2 |= 0x80 ,这一句影响了串口的发送,可是这一句在STC8.h里面说明必须使用。还望各路前辈大神给指点一下!附代码如下:
#include <STC8.h>
#include <intrins.h>
#define FOSC 24000000UL
#define BRT (65536 - FOSC / 115200 / 4)
#define PWM_T 0x1000        // PWM计数器,设置PWM周期为0x1000,即4096
#define PWMnT1 0x0000        //PWM的0通道T1计数值为0
#define PWMnT2 0x0028        //PWM的0通道T2计数值为0x28
#define PWMnCR 0x85
bit busy,p=0;
char wptr;
char rptr;
char buffer[4];
void UartSend(char dat)
{
        while (busy);
        busy = 1;
        SBUF = dat;
}
void UartIsr() interrupt 4 using 1
{
        if (TI)
        {
                TI = 0;
                busy = 0;
        }
        if (RI)
        {
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                while(!RI);
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                while(!RI);
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                wptr = 0x00;
                p=1;
        }
}
void UartInit()
{
        P_SW1 &= ~0xc0;
        SCON = 0x50;
        T2L = BRT;
        T2H = BRT >> 8;
        AUXR = 0x15;
        wptr = 0x00;
        rptr = 0x00;
        TI = 0;
}
void UartSendStr(char *p)
{
        while (*p)
        {
                UartSend(*p++);
        }
}
void main()
{
        unsigned int auto_adjust[8];
        unsigned char adjust_flag=0x00;
        UartInit();
        ES = 1;
        EA = 1;
/************************************以下是PWM的初始化********************************/
        P_SW2 |= 0x80;
        PWMCKS = 0x01;// PWM时钟选择,系统时钟2分频:12MHz,但实际测得的输出是 约2.93kHz
        PWMC = PWM_T;        // PWM计数器,设置PWM周期为0x1000,即4096
       
        PWM0T1 = PWMnT1;
        PWM0T2 = PWMnT2;
        PWM0CR = PWMnCR;
       
        PWM1T1 = PWMnT1;
        PWM1T2 = PWMnT2;
        PWM1CR = PWMnCR;
       
        PWM2T1 = PWMnT1;
        PWM2T2 = PWMnT2;
        PWM2CR = PWMnCR;
       
        PWM3T1 = PWMnT1;
        PWM3T2 = PWMnT2;
        PWM3CR = PWMnCR;
       
        PWM4T1 = PWMnT1;
        PWM4T2 = PWMnT2;
        PWM4CR = PWMnCR;
       
        PWM5T1 = PWMnT1;
        PWM5T2 = PWMnT2;
        PWM5CR = PWMnCR;
               
        PWM6T1 = PWMnT1;
        PWM6T2 = PWMnT2;
        PWM6CR = PWMnCR;
               
        PWM7T1 = PWMnT1;
        PWM7T2 = PWMnT2;
        PWM7CR = PWMnCR;
       
        PWMIF = 0x00;
        PWMCFG &= ~0xc0;
        P_SW2 &= ~0x80;
        IP2H &= ~0x08;
        IP2 |= 0x08;
        PWMCR = 0x80;                                /*PWM0的控制寄存器,PWM输出使能,初始电平=0,
                                                                                                P2脚作为PWM功能脚,使能中断,使能T1翻转点中断*/
                                                                                               
/************************************以上是PWM的初始化********************************/
        while (1)
        {
                if (p)
                {
                        p=0;
                        auto_adjust[buffer[0]] = buffer[2];
                        auto_adjust[buffer[0]] = (auto_adjust[buffer[0]]<<8) + buffer[1];
                        adjust_flag |= 1<<buffer[0];
                        UartSend(buffer[0]);
                        UartSend((auto_adjust[buffer[0]]>>8));
                        UartSend(((auto_adjust[buffer[0]]<<8)>>8));
                }
                _nop_();
                _nop_();
                _nop_();
                UartSend(p);
                _nop_();
                _nop_();
                _nop_();
        }
}


P_SW2必须设置

P_SW2必须设置

相关帖子

libre01| | 2017-5-6 19:16 | 显示全部楼层
通信不成功是收不到数据还是数据传输错误

使用特权

评论回复
wfxsgsg|  楼主 | 2017-5-6 21:13 | 显示全部楼层
本帖最后由 wfxsgsg 于 2017-5-6 21:18 编辑
libre01 发表于 2017-5-6 19:16
通信不成功是收不到数据还是数据传输错误

是收不到数据,但是我屏蔽 P_SW2 |= 0x80 这条语句后就能收到数据了,通讯也正常了。可是屏蔽了 P_SW2 |= 0x80 这条语句后PWM寄存器的设置就不能生效了,主题帖附的图片说明了 P_SW2 |= 0x80 这条语句的重要性

使用特权

评论回复
libre01| | 2017-5-7 09:29 | 显示全部楼层
本帖最后由 libre01 于 2017-5-7 09:55 编辑

你看下头文件中P_SW2定义的地址正确不?用的串口一的话,你把P_SW1&=~0xc0去掉,再运行下

使用特权

评论回复
wfxsgsg|  楼主 | 2017-5-8 09:38 | 显示全部楼层
libre01 发表于 2017-5-7 09:29
你看下头文件中P_SW2定义的地址正确不?用的串口一的话,你把P_SW1&=~0xc0去掉,再运行下 ...

P_SW2的地址没有错,P_SW1去掉运行,也不行。有两条语句:P_SW2 |= 0x80;P_SW2 &= ~0x80;这两句第一个是把最高位置1,第二个是把最高位清零。在主题帖的程序里,他俩之间有20多条语句。如果我把第二条清零语句提前(这样PWM就不正常了,暂且不管他),提前到他俩之间只有极少几条语句,2条1条0条,然后在运行,发现串口工作正常了 。         。另外,我咨询了STC的工程师,他说会不会是我其他寄存器也要用到P_SW2 |= 0x80;P_SW2 &= ~0x80;这两条语句,我检查了一下,其他的寄存器就是串口1和定时器2的了,然而串口和定时器的寄存器都不用那两条语句。

使用特权

评论回复
coody| | 2017-5-8 14:04 | 显示全部楼层
主程序:
P_SW2 |= 0x80;   //访问XSFR
XSFR访问代码
P_SW2 &= ~0x80;   //访问xdata

访问xdata代码略   // 访问xdata

中断里,先保存P_SW2,再根据要访问XSFR还是XDATA RAM来设置P_SW2最高位,处理完成,再恢复P_SW2 的值。
i = P_SW2;   //暂存P_SW2
根据要访问XSFR还是XDATA RAM来设置P_SW2最高位.
处理代码.
P_SW2 = i;   //恢复P_SW2

使用特权

评论回复
wfxsgsg|  楼主 | 2017-5-8 17:09 | 显示全部楼层
本帖最后由 wfxsgsg 于 2017-5-8 17:11 编辑
coody 发表于 2017-5-8 14:04
主程序:
P_SW2 |= 0x80;   //访问XSFR
XSFR访问代码

程序里面好像只用到了特殊功能寄存器(XSFR),就是PWM的那些寄存器;xdata在程序中没有特定指明使用,编译的时候也没有用到xdata。我引入一个变量 i 后,编译烧录运行,还是串口无**常收到数据,只收到了“00 00 ”,电脑发送数据,没有接收反应。现在还是,只要屏蔽了PWM初始化里面的P_SW2 |= 0x80;这条语句,串口就变得一切正常了。我有点怀疑这款芯片有问题。下面是我加入PWM中断函数和局部变量 i 之后的程序,结果串口还是不行。
#include <STC8.h>
#include <intrins.h>
#define FOSC 24000000UL
#define BRT (65536 - FOSC / 115200 / 4)
#define PWM_T 0x1000        // PWM计数器,设置PWM周期为0x1000,即4096
#define PWMnT1 0x0000        //PWM的0通道T1计数值为0
#define PWMnT2 0x0028        //PWM的0通道T2计数值为0x28
#define PWMnCR 0x85
bit busy,p=0;
char wptr,adjust_flag;
char rptr;
char buffer[4];
void UartIsr() interrupt 4 using 1
{
        if (TI)
        {
                TI = 0;
                busy = 0;
        }
        if (RI)
        {
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                while(!RI);
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                while(!RI);
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                wptr = 0x00;
                p=1;
        }
}
void PWM_Isr() interrupt 22 using 3
{
        unsigned char i;
        i = P_SW2;
        P_SW2 |= 0x80;
        if (PWMCFG & 0x80)
                PWMCFG &= ~0x80;
        if (PWMIF & 0x80)
        {
                PWMIF &= ~0x80;
                if(adjust_flag & 0x80)
                {
                        adjust_flag &= ~0x80;
                }
        }
        if (PWMIF & 0x40)
        {
                PWMIF &= ~0x40;
                if(adjust_flag & 0x40)
                {
                        adjust_flag &= ~0x40;
                }
        }
        if (PWMIF & 0x20)
        {
                PWMIF &= ~0x20;
                if(adjust_flag & 0x20)
                {
                        adjust_flag &= ~0x20;
                }
        }
        if (PWMIF & 0x10)
        {
                PWMIF &= ~0x10;
                if(adjust_flag & 0x10)
                {
                        adjust_flag &= ~0x10;
                }
        }
        if (PWMIF & 0x08)
        {
                PWMIF &= ~0x08;
                if(adjust_flag & 0x08)
                {
                        adjust_flag &= ~0x08;
                }
        }
        if (PWMIF & 0x04)
        {
                PWMIF &= ~0x04;
                if(adjust_flag & 0x04)
                {
                        adjust_flag &= ~0x04;
                }
        }
        if (PWMIF & 0x02)
        {
                PWMIF &= ~0x02;
                if(adjust_flag & 0x02)
                {
                        adjust_flag &= ~0x02;
                }
        }
        if (PWMIF & 0x01)
        {
                PWMIF &= ~0x01;
                if(adjust_flag & 0x01)
                {
                        adjust_flag &= ~0x01;
                }
        }
        P_SW2 = i;
}
void UartInit()
{
        P_SW1 &= ~0xc0;
        SCON = 0x50;
        T2L = BRT;
        T2H = BRT >> 8;
        AUXR = 0x15;
        wptr = 0x00;
        rptr = 0x00;
        TI = 0;
}
void UartSend(char dat)
{
        while (busy);
        busy = 1;
        SBUF = dat;
}
void UartSendStr(char *p)
{
        while (*p)
        {
                UartSend(*p++);
        }
}
void main()
{
        unsigned int auto_adjust[8];
        unsigned char i,adjust_flag=0x00;
        UartInit();
        ES = 1;
        EA = 1;
/************************************以下是PWM的初始化********************************/
        i = P_SW2;
        P_SW2 |= 0x80;
        PWMCKS = 0x01;// PWM时钟选择,系统时钟2分频:12MHz,但实际测得的输出是 约2.93kHz
        PWMC = PWM_T;        // PWM计数器,设置PWM周期为0x1000,即4096
       
        PWM0T1 = PWMnT1;
        PWM0T2 = PWMnT2;
        PWM0CR = PWMnCR;
       
        PWM1T1 = PWMnT1;
        PWM1T2 = PWMnT2;
        PWM1CR = PWMnCR;
       
        PWM2T1 = PWMnT1;
        PWM2T2 = PWMnT2;
        PWM2CR = PWMnCR;
       
        PWM3T1 = PWMnT1;
        PWM3T2 = PWMnT2;
        PWM3CR = PWMnCR;
       
        PWM4T1 = PWMnT1;
        PWM4T2 = PWMnT2;
        PWM4CR = PWMnCR;
       
        PWM5T1 = PWMnT1;
        PWM5T2 = PWMnT2;
        PWM5CR = PWMnCR;
               
        PWM6T1 = PWMnT1;
        PWM6T2 = PWMnT2;
        PWM6CR = PWMnCR;
               
        PWM7T1 = PWMnT1;
        PWM7T2 = PWMnT2;
        PWM7CR = PWMnCR;
       
        PWMIF = 0x00;
        PWMCFG &= ~0xc0;
        P_SW2 = i;
        PWMCR = 0x80;                                /*PWM0的控制寄存器,PWM输出使能,初始电平=0,
                                                                                                P2脚作为PWM功能脚,使能中断,使能T1翻转点中断*/
                                                                                               
/************************************以上是PWM的初始化********************************/
        while (1)
        {
                if (p)
                {
                        p=0;
                        auto_adjust[buffer[0]] = buffer[2];
                        auto_adjust[buffer[0]] = (auto_adjust[buffer[0]]<<8) + buffer[1];
                        adjust_flag |= 1<<buffer[0];
                        UartSend(buffer[0]);
                        UartSend((auto_adjust[buffer[0]]>>8));
                        UartSend(((auto_adjust[buffer[0]]<<8)>>8));
                }
                _nop_();
                _nop_();
                _nop_();
                UartSend(p);
                _nop_();
                _nop_();
                _nop_();
        }
}


使用特权

评论回复
coody| | 2017-5-12 23:29 | 显示全部楼层
LZ还没搞好?
我用STC8做的多轴飞控,用了PWM,还用了2个串口,串口1用来调试或数传,串口2用来接收GPS模块,再使用4路(四轴)或6路(六轴)或8路(八轴)PWM控制电机,4路PCA接收遥控信号(PPM信号),姿态计算都是浮点数,飞得很好,并没有发现什么问题。

使用特权

评论回复
清风819| | 2017-5-13 21:26 | 显示全部楼层
本帖最后由 清风819 于 2017-5-13 21:28 编辑
coody 发表于 2017-5-12 23:29
LZ还没搞好?
我用STC8做的多轴飞控,用了PWM,还用了2个串口,串口1用来调试或数传,串口2用来接收GPS模块 ...

请问你用的哪个型号?频率用到多高?使用串口使用内部RC时钟源吗?

使用特权

评论回复
coody| | 2017-5-15 00:03 | 显示全部楼层
清风819 发表于 2017-5-13 21:26
请问你用的哪个型号?频率用到多高?使用串口使用内部RC时钟源吗?

我用的是STC8A8K64S4A12 LQFP44,跑24MHZ,使用内部时钟。姿态解算是125HZ,即8ms解算一次,浮点数处理,计算时间(包括I2C读MPU-6050)大约3ms。

使用特权

评论回复
wfxsgsg|  楼主 | 2017-5-15 13:28 | 显示全部楼层
coody 发表于 2017-5-15 00:03
我用的是STC8A8K64S4A12 LQFP44,跑24MHZ,使用内部时钟。姿态解算是125HZ,即8ms解算一次,浮点数处理, ...

我用的也是STC8A8K64S4A12,LQFP44,D版;内部时钟源24兆赫兹,系统时钟频率是24MHz,PWM采用二分频12MHz,但是,用示波器测得PWM实际频率是2.93kHz,这也是一个小疑问。。那你跑一下我写的这个程序,看看串口能不能通讯?谢谢

使用特权

评论回复
wfxsgsg|  楼主 | 2017-5-22 12:00 | 显示全部楼层
顶!求助大神,还未解决

使用特权

评论回复
dcxq13| | 2017-5-23 08:30 | 显示全部楼层
楼主你现在调试的如何了?!是PWM与串口都不工作还是只正常一个?!

使用特权

评论回复
wfxsgsg|  楼主 | 2017-5-23 09:26 | 显示全部楼层
dcxq13 发表于 2017-5-23 08:30
楼主你现在调试的如何了?!是PWM与串口都不工作还是只正常一个?!

没有进展。目前还是,PWM可以正常工作,串口不能和“stc-isp的串口助手”通讯,串口助手我截了图。C语言代码那里,只要屏蔽 P_SW2 |= 0x80;这条语句,串口就可以正常收发通讯了,可是这条语句对于初始化PWM寄存器是必须的,没了它,PWM就不行了。
QQ截图20170523091912.png

使用特权

评论回复
wfxsgsg|  楼主 | 2017-6-1 11:01 | 显示全部楼层
【结贴啦!】【问题已解决】真正的问题原因,芯片不稳定,8路PWM同时翻转导致单片机崩溃,因此串口也不能用了;解决方法:把每一路的翻转值(PWMnT1和PWMnT2,n=0,1,2....,7)调为不同(相差1即可),单片机就可正常工作。附调试好的代码
#include <STC8.h>
#include <intrins.h>
#define FOSC 24000000UL
#define BRT (65536 - FOSC / 115200 / 4)
#define PWM_T 0x1000        // PWM计数器,设置PWM周期为0x1000,即4096
#define PWMnT1 0x0000        //PWM的0通道T1计数值为0
#define PWMnT2 0x0028        //PWM的0通道T2计数值为0x28
#define PWMnCR 0x85
bit busy,p=0;
char wptr,adjust_flag;
char rptr;
char buffer[4];
void UartIsr() interrupt 4 using 1
{
        if (TI)
        {
                TI = 0;
                busy = 0;
        }
        if (RI)
        {
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                while(!RI);
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                while(!RI);
                RI = 0;
                buffer[wptr++] = SBUF;
                wptr &= 0x03;
                wptr = 0x00;
                p=1;
        }
}
void PWM_Isr() interrupt 22 using 3
{
        unsigned char i;
        i = P_SW2;
        P_SW2 |= 0x80;
        if (PWMCFG & 0x80)
                PWMCFG &= ~0x80;
        if (PWMIF & 0x80)
        {
                PWMIF &= ~0x80;
                if(adjust_flag & 0x80)
                {
                                                adjust_flag &= ~0x80;
                }
        }
        if (PWMIF & 0x40)
        {
                PWMIF &= ~0x40;
                if(adjust_flag & 0x40)
                {
                                                adjust_flag &= ~0x40;
                }
        }
        if (PWMIF & 0x20)
        {
                PWMIF &= ~0x20;
                if(adjust_flag & 0x20)
                {
                                                adjust_flag &= ~0x20;
                }
        }
        if (PWMIF & 0x10)
        {
                PWMIF &= ~0x10;
                if(adjust_flag & 0x10)
                {
                                                adjust_flag &= ~0x10;
                }
        }
        if (PWMIF & 0x08)
        {
                PWMIF &= ~0x08;
                if(adjust_flag & 0x08)
                {
                                                adjust_flag &= ~0x08;
                }
        }
        if (PWMIF & 0x04)
        {
                PWMIF &= ~0x04;
                if(adjust_flag & 0x04)
                {
                                                adjust_flag &= ~0x04;
                }
        }
        if (PWMIF & 0x02)
        {
                PWMIF &= ~0x02;
                if(adjust_flag & 0x02)
                {
                                                adjust_flag &= ~0x02;
                }
        }
        if (PWMIF & 0x01)
        {
                PWMIF &= ~0x01;
                if(adjust_flag & 0x01)
                {
                                                adjust_flag &= ~0x01;
                }
        }
        P_SW2 = i;
}
void UartInit()
{
        P_SW1 &= ~0xc0;
       
        /*P3.0是RXD,receive,接收,属于输入模式,所以不能设为强推挽输出*/
       
        P3M0 |= 0x02;
        P3M0 &= ~0x01;
        P3M1 &= ~0x03;//强推挽输出
        SCON = 0x50;
        T2L = BRT;
        T2H = BRT >> 8;
        AUXR = 0x15;
        wptr = 0x00;
        rptr = 0x00;
        TI = 0;
}
void UartSend(char dat)
{
        while (busy);
        busy = 1;
        SBUF = dat;
}
//void UartSendStr(char *p)
//{
//        while (*p)
//        {
//                UartSend(*p++);
//        }
//}
void main()
{
        unsigned int auto_adjust[8];
        unsigned char i,adjust_flag=0x00;
        UartInit();
        ES = 1;
        EA = 1;
/************************************以下是PWM的初始化********************************/
        i = P_SW2;
        P_SW2 |= 0x80;
        PWMCKS = 0x01;// PWM时钟选择,系统时钟2分频:12MHz,但实际测得的输出是 约2.93kHz
        PWMC = PWM_T;        // PWM计数器,设置PWM周期为0x1000,即4096
       
        PWM0T1 = PWMnT1;
        PWM0T2 = PWMnT2+1;
        PWM0CR = PWMnCR;
       
        PWM1T1 = PWMnT1+2;
        PWM1T2 = PWMnT2+3;
        PWM1CR = PWMnCR;
       
        PWM2T1 = PWMnT1+4;
        PWM2T2 = PWMnT2+5;
        PWM2CR = PWMnCR;
       
        PWM3T1 = PWMnT1+6;
        PWM3T2 = PWMnT2+7;
        PWM3CR = PWMnCR;
       
        PWM4T1 = PWMnT1+8;
        PWM4T2 = PWMnT2+9;
        PWM4CR = PWMnCR;
       
        PWM5T1 = PWMnT1+10;
        PWM5T2 = PWMnT2+11;
        PWM5CR = PWMnCR;
                                 
        PWM6T1 = PWMnT1+12;
        PWM6T2 = PWMnT2+13;
        PWM6CR = PWMnCR;
                                 
        PWM7T1 = PWMnT1+14;
        PWM7T2 = PWMnT2+15;
        PWM7CR = PWMnCR;
       
        PWMIF = 0x00;
        PWMCFG &= ~0xc0;
        P_SW2 = i;
        PWMCR = 0x80;                                /*PWM0的控制寄存器,PWM输出使能,初始电平=0,
                                                                                                                                                                                                                                                                                                                                                                        P2脚作为PWM功能脚,使能中断,使能T1翻转点中断*/
                                                                                                                                                                                                                                                                                                                                                                       
/************************************以上是PWM的初始化********************************/
        while (1)
        {
                if (p)
                {
                        p=0;
                        auto_adjust[buffer[0]] = buffer[1];
                        auto_adjust[buffer[0]] = (auto_adjust[buffer[0]]<<8) + buffer[2];
                        adjust_flag |= 1<<buffer[0];
                        UartSend(buffer[0]);
                        UartSend((auto_adjust[buffer[0]]>>8));
                        UartSend(((auto_adjust[buffer[0]]<<8)>>8));
                }
        }
}


使用特权

评论回复
datouyuan| | 2017-6-1 11:57 | 显示全部楼层
wfxsgsg 发表于 2017-6-1 11:01
【结贴啦!】【问题已解决】真正的问题原因,芯片不稳定,8路PWM同时翻转导致单片机崩溃,因此串 ...

你靠近mcu有没有滤波电容?会不会是由于这原因?

使用特权

评论回复
wfxsgsg|  楼主 | 2017-6-2 14:41 | 显示全部楼层
datouyuan 发表于 2017-6-1 11:57
你靠近mcu有没有滤波电容?会不会是由于这原因?

真正的原因是这款stc单片机承受不了8路同频同相的PWM运转,导致单片机崩溃(进而包括串口在内的等功能都不能使用了)。解决方法,错开PWM的翻转置。

使用特权

评论回复
datouyuan| | 2017-6-2 14:51 | 显示全部楼层
wfxsgsg 发表于 2017-6-2 14:41
真正的原因是这款stc单片机承受不了8路同频同相的PWM运转,导致单片机崩溃(进而包括串口在内的等功能都 ...

这原因站不住脚。

使用特权

评论回复
wfxsgsg|  楼主 | 2017-6-3 09:13 | 显示全部楼层
datouyuan 发表于 2017-6-2 14:51
这原因站不住脚。

真正的原因是,STC8A8K64S4A12,这款单片机是新品,有很多功能还没稳定,目前还在试产阶段。就是芯片不行,芯片不行!我也很无奈

使用特权

评论回复
领创电子MCU| | 2017-6-5 11:27 | 显示全部楼层
一定要用STC的吗?用华大半导体的M0 或者 昂宝的8位机也可以的     QQ  20328568

使用特权

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

本版积分规则

4

主题

29

帖子

0

粉丝