930电子网

 找回密码
 立即注册
艾克姆科技推出最新产品STC32G12K128开发板
查看: 13122|回复: 8

串口 求版主指导

[复制链接]

2

主题

10

帖子

72

积分

注册会员

Rank: 2

积分
72
发表于 2020-4-28 11:45:32 | 显示全部楼层 |阅读模式
本帖最后由 Sivan 于 2020-4-28 11:49 编辑

各位大神,我在程序中加入这部分PWM翻转赋值之后,然后串口助手就都不显示数据了,屏蔽掉就正常了,但是寄存器之类的也不冲突啊。求指导!file:///C:/Users/苏曦Sivan/AppData/Roaming/Tencent/QQTempSys/E9BIPM$_%609%7D%60VS07%60VD9H1F.gif

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

2

主题

10

帖子

72

积分

注册会员

Rank: 2

积分
72
 楼主| 发表于 2020-4-28 11:48:18 | 显示全部楼层
求版主指导
回复 支持 反对

使用道具 举报

101

主题

333

帖子

7428

积分

版主

Rank: 7Rank: 7Rank: 7

积分
7428
发表于 2020-4-28 15:38:49 | 显示全部楼层
这个问题需要去从下面几个点分析:
1、中断,多个外设中断都打开的话,在执行时分析中断执行情况,是否CPU正处于响应另一个外设,那么串口可能就漏数据。
2、检查主循环代码对程序执行的任务分配是否合理,高效的代码主循环时间都不长,切记有延时等占用CPU资源代码。
3、单片机要是支持硬件仿真的话,可以仿真看下程序执行情况。
回复 支持 反对

使用道具 举报

2

主题

10

帖子

72

积分

注册会员

Rank: 2

积分
72
 楼主| 发表于 2020-4-29 00:45:30 | 显示全部楼层
经过逐步排查发现配置PWMCR寄存器串口就不会输出,串口助手上没有任何东西。
1)关于中断:在程序中只有CCP脉冲捕捉中断,并且经过测试发现其对输出无影响;
2)在主函数中只有PCA脉冲捕捉、四路增强型PWM输出、串口传输捕捉到的脉冲数三部分,其余都是简单的算法,延时只有一个delay_ms(5),测试屏蔽PWM,其余都可正常运行;
3)硬件仿真应该是可以的,STC8A8K64S12A芯片,在尽力学习中

另外,我在网上也有搜索到关于这个芯片也有别人出现类似现象,他的情况说是由于芯片不稳定,8路PWM同时翻转导致单片机崩溃,因此串口也不能使用了,不知我这程序是否存在可能?但是我只有四路PWM并且也不是同时翻转啊
回复 支持 反对

使用道具 举报

2

主题

10

帖子

72

积分

注册会员

Rank: 2

积分
72
 楼主| 发表于 2020-4-29 00:49:10 | 显示全部楼层
另外我是在EASY  STC8A8K64S12A开发板上运行的,不知道是否有可能是在开发板上有部分引脚冲突?
回复 支持 反对

使用道具 举报

101

主题

333

帖子

7428

积分

版主

Rank: 7Rank: 7Rank: 7

积分
7428
发表于 2020-4-29 09:32:52 | 显示全部楼层
你的逻辑性是很强的,关于STC的PWM外设使用时确实需要考虑芯片本身是否存在BUG,这个建议和STC官方沟通下。另外,针对开发板引脚使用是否被其他电路占用,请参考艾克姆提供的开发板原理图。
回复 支持 反对

使用道具 举报

101

主题

333

帖子

7428

积分

版主

Rank: 7Rank: 7Rank: 7

积分
7428
发表于 2020-4-29 09:33:47 | 显示全部楼层
代码可截图附一下。
回复 支持 反对

使用道具 举报

2

主题

10

帖子

72

积分

注册会员

Rank: 2

积分
72
 楼主| 发表于 2020-4-30 00:52:38 | 显示全部楼层
#include "stc8.h"                         //STC头文件
#include "def.h"                               //宏定义 常用函数
#include "math.h"
#include "stdio.h"

char S[10]={0,0,0,0,'M'};        //定义到程序空间中

u16  M1=512,M2=0;       //存储PCA脉冲捕捉次数

void delay_us(u16 us)          //20MHz晶振
{
  u16 i;
  u8 m;
  for(i=0;i<us;i++)
  for(m=0;m<2;m++);
}


/*******************************************编码器CCP脉冲捕捉*********************************/
void PCAInit()                   //PCA初始化
{
        P_SW1 |= 0X10;                 //**01**** 脉冲捕捉端口
        P_SW1 &= 0XDF;       
        CCON = 0x00;                    //CF、CR均零,PCA中断标志清零
        CMOD &= 0x7F;                   //CIDL位置0,空闲模式下PCA计数器仍然工作
        CMOD &= 0xF9;                   //CP2、CP1、CP0设置为100,PCA时钟源选择为系统时钟         1/20 us
        CMOD |= 0x08;                   //CP2、CP1、CP0设置为100,PCA时钟源选择为系统时钟
        CMOD |= 0x01;                   //ECF位置1,允许寄存器CCON中CF位中断(PCA计时中断)     (2^16)/20 us = 3276.8 us =3.2768 ms
        CL = 0x00;                      //PCA计数器赋初值
        CH = 0x00;                      //PCA计数器赋初值
       
        CCAPM1 &= 0xBF;                 //ECOM1位置0,禁止比较器功能
        CCAPM1 &= 0xDF;                 //CAPP2位置0,禁止上升沿捕获
        CCAPM1 |= 0x10;                 //CAPN2位置1,允许下降沿捕获
        CCAPM1 &= 0xF7;                 //MAT1位置0,禁止匹配控制位
        CCAPM1 &= 0xFB;                 //TOG1位置0,禁止翻转控制位
        CCAPM1 &= 0xFD;                 //PWM1位置0,禁止PWM模式
        CCAPM1 |= 0x01;                 //ECCF1位置1,允许CCF1中断
        CCAP1L = 0x00;                  //PCA捕获值寄存器赋初值      
        CCAP1H = 0x00;                  //PCA捕获值寄存器赋初值   
       
        CCAPM2 &= 0xBF;                 //ECOM2位置0,禁止比较器功能
        CCAPM2 &= 0xDF;                 //CAPP2位置0,禁止上升沿捕获
        CCAPM2 |= 0x10;                 //CAPN2位置1,允许下降沿捕获
        CCAPM2 &= 0xF7;                 //MAT2位置0,禁止匹配控制位
        CCAPM2 &= 0xFB;                 //TOG2位置0,禁止翻转控制位
        CCAPM2 &= 0xFD;                 //PWM2位置0,禁止PWM模式
        CCAPM2 |= 0x01;                 //ECCF2位置1,允许CCF2中断
        CCAP2L = 0x00;                  //PCA捕获值寄存器赋初值      
        CCAP2H = 0x00;                  //PCA捕获值寄存器赋初值   
       
}



void PCA_int () interrupt 7             //PCA中断服务程序
{
        if(CF)                                 //PCA计数器溢出
        {
                //V0 = (M0/1.024)* 1950 * PI/2 ;    //速度 = ( (总脉冲数M / 编码器线数1024)  * 编码器齿数 30/ 车模齿数20 ) * 轮周长65直径 / 脉冲读取时间2ms。
    CF = 0;                                //将PCA计数器阵列溢出标志位软件清零
        }               
        if(CCF1)                               //CCF1捕获中断
        {
                M1++;
    CCF1 = 0;                            //将标志位软件清零
                }       
        if(CCF2)                               //CCF3捕获中断
        {               
                M2++;
    CCF2 = 0;                            //将标志位软件清零
                }       
}

/******************************************电机PWM驱动*************************************************/
void PWM_Configuration()    //PWM进行初始化
{
        PWMCFG &= 0xBF;                         //将ETADC位置0,即PWM与ADC不关联
        PWMCFG &= 0x7F;                         //将CBIF位置0,PWM计数器归零中断标志位,需软件清零

        P_SW2 |= 0x80;                         //将EAXSFR位置1,以访问PWM在扩展RAM区的特殊功能寄存器
       
        //对PWM0的初始化部分
        PWM0CR &= 0xEF;                   //将C0_S[1:0]位置0 1,选择PWM0的输出引脚是P1.0
        PWM0CR |= 0x08;                   //将C0_S[1:0]位置0 1,选择PWM0的输出引脚是P1.0
        PWM0CR |= 0x80;                               //将ENC0O位置1,PWM0的端口为PWM输出口,受PWM波形发生器控制       
        PWM0CR |= 0x40;;                         //将C0INI位置0,设置PWM0输出端口的初始电平为低电平
        PWMIF &= 0xFE;                         //将C0IF位置0,PWM0中断标志位,需软件清零
        PWM0CR |= 0x04;                   //将EC0I位置1,使能PWM0中断
        PWM0CR &= 0xFD;                   //将EC0T2SI位置0,关闭T2翻转时中断
        PWM0CR &= 0xFE;                   //将EC0T1SI位置0,关闭T1翻转时中断
       
        //对PWM1的初始化部分
        PWM1CR &= 0xEF;                   //将C0_S[1:0]位置0 1,选择PWM1的输出引脚是P1.1
        PWM1CR |= 0x08;                   //将C0_S[1:0]位置0 1,选择PWM1的输出引脚是P1.1
        PWM1CR |= 0x80;                               //将ENC0O位置1,PWM0的端口为PWM输出口,受PWM波形发生器控制       
        PWM1CR |= 0x40;;                         //将C0INI位置0,设置PWM1输出端口的初始电平为低电平
        PWMIF &= 0xFD;                         //将C0IF位置0,PWM1中断标志位,需软件清零
        PWM1CR |= 0x04;                   //将EC0I位置1,使能PWM1中断
        PWM1CR &= 0xFD;                   //将EC0T2SI位置0,关闭T2翻转时中断
        PWM1CR &= 0xFE;                   //将EC0T1SI位置0,关闭T1翻转时中断
       
        //对PWM2的初始化部分
        PWM2CR &= 0xEF;                   //将C0_S[1:0]位置0 1,选择PWM2的输出引脚是P1.2
        PWM2CR |= 0x08;                   //将C0_S[1:0]位置0 1,选择PWM2的输出引脚是P1.2
        PWM2CR |= 0x80;                               //将ENC0O位置1,PWM2的端口为PWM输出口,受PWM波形发生器控制       
        PWM2CR |= 0x40;;                         //将C0INI位置0,设置PWM2输出端口的初始电平为低电平
        PWMIF &= 0xFC;                         //将C0IF位置0,PWM2中断标志位,需软件清零
        PWM2CR |= 0x04;                   //将EC0I位置1,使能PWM2中断
        PWM2CR &= 0xFD;                   //将EC0T2SI位置0,关闭T2翻转时中断
        PWM2CR &= 0xFE;                   //将EC0T1SI位置0,关闭T1翻转时中断
       
        //对PWM3的初始化部分
        PWM3CR &= 0xEF;                   //将C0_S[1:0]位置0 1,选择PWM3的输出引脚是P1.3
        PWM3CR |= 0x08;                   //将C0_S[1:0]位置0 1,选择PWM3的输出引脚是P1.3
        PWM3CR |= 0x80;                               //将ENC0O位置1,PWM3的端口为PWM输出口,受PWM波形发生器控制       
        PWM3CR |= 0x40;                         //将C0INI位置1,设置PWM3输出端口的初始电平为高电平
        PWMIF &= 0xF7;                         //将C0IF位置0,PWM3中断标志位,需软件清零
        PWM3CR |= 0x04;                   //将EC0I位置1,使能PWM3中断
        PWM3CR &= 0xFD;                   //将EC0T2SI位置0,关闭T2翻转时中断
        PWM3CR &= 0xFE;                   //将EC0T1SI位置0,关闭T1翻转时中断
       
        PWMCKS = 0x00 ;            //系统时钟
        PWMC = 0x2000 ;            //设置PWM周期为2^10个时钟  8192
        P_SW2 &= 0x7F;                         //将EAXSFR位置0,恢复访问XRAM
       
               
          //对PWM翻转计数器赋初值
    PWM0T1 = 0x0000;              //赋值PWM0第一次翻转计数器值   初始为高电平
                PWM0T2 = 0x0000;              //赋值PWM0第二次翻转计数器值   相同跳过,一直为低电平
                //占空比0
       
    PWM1T1 = 0x0000;             //赋值PWM1第一次翻转计数器值(不断变化值)
                PWM1T2 = 0X1000;              //赋值PWM1第二次翻转计数器值(定值)
          //占空比50%
       
                PWM2T1 = 0x0000;             //赋值PWM2第一次翻转计数器值(不断变化值)
                PWM2T2 = 0x0001;              //赋值PWM2第二次翻转计数器值(定值)
          //占空比100%
       
                PWM3T1 = 0x0000;             //赋值PWM3第一次翻转计数器值(不断变化值)
                PWM3T2 = 0x0000;              //赋值PWM3第二次翻转计数器值(定值)
                //占空比0
                                       
        //PWM外部异常控制寄存器的操作
        PWMFDCR &= 0xDF;                       //将ENFD位置0,关闭PWM外部异常检测功能
        PWMFDCR &= 0xF7;                       //将ENDI位置0,关闭PWM异常检测中断
        PWMFDCR &= 0xFB;                       //将FDCMP位置0,比较器与PWM无关
        PWMFDCR &= 0xFD;                       //将FDIO位置0,P3.5的状态与PWM无关
        PWMFDCR &= 0xFE;                       //将FDIF位置0,PWM异常检测中断标志位,需软件清零
        IP2 |= 0x40;                           //将PPWM位置1,使能PWM中断为最高优先级中断
       
        //使能PWM波形发生器
        PWMCR |= 0x40;                         //将ECBI位置1,使能PWM计数器归零中断

}

                                                                                                                                                                                               


void ISP_Check()                                                //串口发送调用函数  串口1波特率为9600  STC内部晶振频率为11.0592MHz
{
  unsigned char a;         

          a=0;
           while(S[a]!= '\0')
              {
                SBUF = S[a];                //SUBF接受/发送缓冲器(又叫串行通信特殊功能寄存器)
         while(!TI);                        //等特数据传送        (TI发送中断标志)
                 TI = 0;                                        // 清除数据传送标志       
                 a++;                                            // 下一个字符
       }
}


void main()
{         
           P1M1 &= 0xF0;        P1M0 &= 0xF0;
    PWM_Configuration();              //初始化PWM口
                PCAInit();                        //脉冲捕捉初始化
          
          SCON=0x50;                        //REN=1允许串行接受状态,串口工作模式2               
          TMOD= 0x00;                       //定时器1为模式0(16位自动重载)               
          AUXR=0X40;                                    //开启1T模式
    TL1=(65535-(11059200/4/9600));    //设置波特率重装值
          TH1=(65535-(11059200/4/9600))>>8;

                TR1  = 1;        //开启定时器1                                                                     
                EA   = 1;        // 开总中断
       
        while(1)
        {  
          S[0]=M1/100000+'0';         //取万位
          S[1]=(M1/10000)%10+'0';         //取万位        //3ms 30
          S[2]=(M1/1000)%10+'0';     //取千位
          S[3]=(M1/1000)%10+'0';      //取百位
                S[4]=(M1/100)%10+'0';      //取十位
    S[5]=M1%10+'0';           //取个位
    S[6]=",";
          S[7]='\0';
  
                ISP_Check();         //发送数据
   
                P_SW2 |= 0x80;                            //将EAXSFR位置1,以访问PWM在扩展RAM区的特殊功能寄存器
          PWMCR |= 0x80;                            //将ENPWM位置1,使能PWM波形发生器,PWM计数器开始计数
               
    PWM0T1 = 0x0001;              //赋值PWM0第一次翻转计数器值   初始为高电平
                PWM0T2 = 0x01FF;              //赋值PWM0第二次翻转计数器值   相同跳过,一直为低电平
                //占空比
       
    PWM1T1 = 0X01FE;              //赋值PWM1第一次翻转计数器值(不断变化值)
                PWM1T2 = 0x01FF;              //赋值PWM1第二次翻转计数器值(定值)
          //占空比
       
                PWM2T1 = 0x0000;              //赋值PWM2第一次翻转计数器值(不断变化值)
                PWM2T2 = 0x0001;              //赋值PWM2第二次翻转计数器值(定值)
          //占空比100%
       
                PWM3T1 = 0x0000;              //赋值PWM3第一次翻转计数器值(不断变化值)
                PWM3T2 = 0x0000;              //赋值PWM3第二次翻转计数器值(定值)
                 //占空比0

                M1=0;                       //清零
                M2=0;
                CR = 1;         //启动PCA计数器阵列计数
    delay_us(100);       
}
        }
回复 支持 反对

使用道具 举报

2

主题

10

帖子

72

积分

注册会员

Rank: 2

积分
72
 楼主| 发表于 2020-4-30 00:54:18 | 显示全部楼层
程序如上,麻烦版主看看。感谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|官方淘宝店|930电子网 ( 皖ICP备16000695号-2 )

Copyright © 合肥艾克姆电子科技有限公司
快速回复 返回顶部 返回列表