ecoo 发表于 2023-2-22 09:14:22

STC8G1KO8A取代STC15W104中遇到的问题

本帖最后由 ecoo 于 2023-2-22 11:34 编辑

最近在移植一段开源的电调程序到stc8G1K08A,根据手册指引;
改了include,增加了STC8G.h和intrins.h

改了IO配置;
增加了eeprom的iap_tps指令;
复位脚用作IO输出,未改动;
初始化中配置了引脚准双向;
根据例程的eeprom基础操作改了程序的eeprom操作。

编译过程未报错,实际下载程序后,能看到初始化的输出波形,但是主程序没反应,请大佬指正下程序哪里没改到位。
#include<STC8G.h>
#include<intrins.h>
#define u8 unsigned char
#define u16 unsigned int

sbit IN=P5^4;                              //修改引脚定义
//sbit Mode_IN=P5^5;                     //模式引脚

sbit A1=P3^3;
sbit A2=P3^2;
sbit B1=P3^1;
sbit B2=P3^0;

bit turn;
bit stop,go;
bit ok,lose,error;
bit mode;
u8 MARK1,MARK2,low,top,calabration,over,n;
u8 step;
u16 time,tt ;
u16 MAX,MINE,MIDDLE,k;                        //修改冲突的min>>mine
u16 Timer2_value;
u16 phase_time;
int speed;

void Delay100us()                                          //@12.000MHz,修改为Y6指令集
{
        unsigned char i, j;
        _nop_();
        i = 2;
        j = 140;
        do
        {
                while (--j);
        } while (--i);
}

void delay(u16 t)
{
        while(t--)
        Delay100us();
}

u8 EEPROM_read(u8 address)
{
    char byte;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 1;                              //设置IAP读命令
    IAP_ADDRL = address;                        //设置IAP低地址
    IAP_ADDRH = address >> 8;                   //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    byte = IAP_DATA;                            //读IAP数据
    IAP_CONTR = 0;                              //关闭IAP功能
    return byte;
}

void EEPROM_write(u8 address,u8 byte)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 2;                              //设置IAP写命令
    IAP_ADDRL = address;                        //设置IAP低地址
    IAP_ADDRH = address >> 8;                   //设置IAP高地址
    IAP_DATA = byte;                            //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IAP_CONTR = 0;
        //         IAP_CONTR=0x80;                           //以下为源程序eeprom操作
//IAP_ADDRL=address;
//IAP_DATA=byte;
//IAP_CMD=0x02;
//IAP_TRIG=0x46;
//IAP_TRIG=0xb9;
       
}

void EEPROM_clean(u8 address)
{
          IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 3;                              //设置IAP擦除命令
    IAP_ADDRL = address;                        //设置IAP低地址
    IAP_ADDRH = address >> 8;                   //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IAP_CONTR = 0;                              //关闭IAP功能
// IAP_CONTR=0x80;                              //源程序eeprom操作
//IAP_ADDRL=address;
//IAP_CMD=0x03;
//IAP_TRIG=0x46;
//IAP_TRIG=0xb9;
}

void DATA_read()
{
IAP_CONTR=0x83;                              //修改
IAP_TPS = 12;                                  //设置等待参数12MHz
MARK1=EEPROM_read(0);
MARK2=EEPROM_read(1);
MAX=EEPROM_read(2);
MAX<<=8;
MAX+=EEPROM_read(3);
MIDDLE=EEPROM_read(4);
MIDDLE<<=8;
MIDDLE+=EEPROM_read(5);
IAP_CONTR=0;
}

void DATA_save()
{
IAP_CONTR=0x83;                              //修改
IAP_TPS = 12;                                  //设置等待参数12MHz
EEPROM_clean(0);
EEPROM_write(0,0x0f);
EEPROM_write(1,0xa5);
EEPROM_write(2,MAX>>8);
EEPROM_write(3,MAX);
EEPROM_write(4,MIDDLE>>8);
EEPROM_write(5,MIDDLE);
IAP_CONTR=0;
}

void measure()
{
        time=0;
        TL0=0,TH0=0;
        while(!IN);
        TR0=1;
        while(IN);
        TR0=0;
        time=TH0;
        time<<=8;
        time+=TL0;               
}

void shock(u8 n)                              //beep
{
        u8 i;
        for(i=0;i<250;i++)
        {
                A1=1;A2=0;
                delay(n);
                A1=0;A2=1;
                delay(n);       
        }
        A1=0;A2=0;
}

void initial()
{
        u8 i;       
       
        P3M1=0x00;                                        //修改准双向
        P3M0=0x00;
        P5M1=0x00;       
        P5M0=0x00;
        TMOD=0x01;

        A1=0;
        A2=0;
        B1=0;
        B2=0;
       
        delay(2000);
        shock(2);                                            //上电能观察到输出
        shock(3);
        shock(4);
        delay(5000);
       
//        mode=Mode_IN;
        mode=1;                                       //1为2相,0取四相

        measure();
        measure();
        measure();
        measure();
        measure();
       
       
        DATA_read();
        if(MARK1!=0x0f||MARK2!=0xa5)                  //16bit,if((MARK1==0x0f)&&(MARK2==0xa5))
        {
               
                MAX=1950;MIDDLE=1500;                     //默认标准行程
               
        }
       
        over=1;
        while(over)
        {
                measure();
               
                if(time>1700)                               //上电油门高位校准行程
                {
                        i++;
                        if(i>100)over=0,calabration=1;            //校准
                }
                else               
                {
                        if(time<MIDDLE+50&&time>MIDDLE-50)      //校准完成
                        {
                                over=0;
                                shock(4);
                                shock(3);
                                shock(2);

                        }
                }
        }       

        if(MAX>2200||MIDDLE<1300)
        {
                calabration=1;
                if(MAX<1700||MIDDLE>1700)calabration=1;
        }
       
        if(calabration)
        {
                over=1;
                while(over)
                {
                        measure();
                        if(time>1700)over=0;
                }
                delay(5000);delay(5000);
                shock(4);
                delay(2000);
                shock(4);
                measure();
                measure();
                if(time>1700&&time<2200)MAX=time;
                else error=1;       
               
                over=1;
                while(over)
                {
                        measure();
                        if(time<1700&&time>1300)over=0;
                }       
                delay(5000);delay(5000);
                shock(4);
                delay(2000);
                shock(4);
                measure();
                measure();
                if(time>1300&&time<1700)MIDDLE=time;
                else error=1;
               
                if(error==0)DATA_save();

                delay(2000);
                shock(4);
                shock(3);
                shock(2);
        }
       
}

main()
{
        initial();
        stop=1;
        IE=0x80;                                    //中断
        IE2=0x04;

        MINE=MIDDLE+MIDDLE-MAX;
        k=MAX-MIDDLE;

        AUXR=0x10;                                    //开定时器2
        while(1)                                    //正常工作
        {
               measure();
//                shock(2);                                 //测试主程序循环用方波
                if(lose)                                    //失控待机
                {
                        delay(1000);
                        measure();
                        measure();
                }

                if(time>800&&time<2200)                     //主程序
                {
                       
                        ok=1;lose=0;
                       
                        if(time>MIDDLE+50)
                        {
                                stop=0,go=1;
       
                                if(time>MAX)time=MAX;
               
                                speed=(long)(time-MIDDLE )*100/k;
                               
                                phase_time=11000-speed*100;             //11ms~1ms换向时间调节,最大0.4ms,取值范围10400~11000(根据电机)

                                Timer2_value=65535-phase_time;
                        }
                        else if(time<MIDDLE-50)
                        {
                                stop=0,go=0;
       
                                if(time<MINE)time=MINE;
               
                                speed=(long)(MIDDLE- time)*100/k;

                                phase_time=11000-speed*100;

                                Timer2_value=65535-phase_time;
                        }
                        else
                        {
                                stop=1;
                        }
                                               
                }
                       
        }
}

void et2()interrupt 12                        //定时驱动
{

        if(stop)                                    //停止
        {
                T2L=0x18,T2H=0xfc;                        //1ms
                A1=0,A2=0,B1=0,B2=0;
        }
        else                                          //转动
        {
                T2L=Timer2_value,T2H=Timer2_value>>8;       //11ms~1ms换向时间调节
               
                if(mode)                                    //两相 8拍,MODE=1
                {
                        if(step==0)A1=1,A2=0,B1=0,B2=0;
                        else if(step==1)A1=1,A2=0,B1=1,B2=0;
                        else if(step==2)A1=0,A2=0,B1=1,B2=0;
                        else if(step==3)A1=0,A2=1,B1=1,B2=0;
                        else if(step==4)A1=0,A2=1,B1=0,B2=0;
                        else if(step==5)A1=0,A2=1,B1=0,B2=1;
                        else if(step==6)A1=0,A2=0,B1=0,B2=1;
                        else if(step==7)A1=1,A2=0,B1=0,B2=1;
                }
                else                                        //四相 8拍,MODE=0
                {
                        if(step==0)A1=1,A2=0,B1=0,B2=0;
                        else if(step==1)A1=1,A2=1,B1=0,B2=0;
                        else if(step==2)A1=0,A2=1,B1=0,B2=0;
                        else if(step==3)A1=0,A2=1,B1=1,B2=0;
                        else if(step==4)A1=0,A2=0,B1=1,B2=0;
                        else if(step==5)A1=0,A2=0,B1=1,B2=1;
                        else if(step==6)A1=0,A2=0,B1=0,B2=1;
                        else if(step==7)A1=1,A2=0,B1=0,B2=1;
                }       
               
                if(go)                                    //正转
                {
                        step++;
                        if(step>7)step=0;
                }
                else                                        //反转
                {
                        if(step)step--;
                        else step=7;
                }

        }

        tt++;
        if(ok)tt=0;
        else {if(tt>200)tt=200,stop=1,lose=1;}      //信号断开检测
        ok=0;
}


梁工 发表于 2023-2-22 09:42:52

临时借用一个IO放在主程序中取反,示波器看是否输出方波,看看主程序是否在循环。

AI-32位8051 发表于 2023-2-22 13:22:43

   楼主可以参考STC8G资料附录X部分:STC8G单片机取代STC15系列的注意事项:下载链接如下:

   https://www.stcai.com/cp_stc8gxl

ecoo 发表于 2023-2-22 21:16:33

梁工 发表于 2023-2-22 09:42
临时借用一个IO放在主程序中取反,示波器看是否输出方波,看看主程序是否在循环。 ...

方波有输出,主程序循环中

ecoo 发表于 2023-2-22 21:17:29

STCAI-32位8051 发表于 2023-2-22 13:22
楼主可以参考STC8G资料附录X部分:STC8G单片机取代STC15系列的注意事项:下载链接如下:

   https:// ...

帖子开头已经对照着手册这一段一条条改过去了

梁工 发表于 2023-2-23 10:06:06

ecoo 发表于 2023-2-22 21:16
方波有输出,主程序循环中

那你说“主程序没反应”就不是了,主程序在循环中,可能是某个外设没初始化对。问题描述再细化一点,是哪个外设功能没输出?

ecoo 发表于 2023-2-23 10:56:20

梁工 发表于 2023-2-23 10:06
那你说“主程序没反应”就不是了,主程序在循环中,可能是某个外设没初始化对。问题描述再细化一点,是哪 ...

程序上电后输出方波,然后测量输入得pmw,在范围内正常工作,根据输入pmw宽度输出4路pmw,输入不在范围内就重新测量范围,然后写入eeprom,源程序在15w上工作正常,移植过程中未改动main、measure里面的代码。实际是只能看到上电的波形,后面输出引脚无反应了。在循环中加入直接输出,输出引脚正常输出.

梁工 发表于 2023-2-23 11:06:00

ecoo 发表于 2023-2-23 10:56
程序上电后输出方波,然后测量输入得pmw,在范围内正常工作,根据输入pmw宽度输出4路pmw,输入不在范围内 ...

你分两步,先测试PWM输出,给定一个占空比,看PWM是否能连续输出,能则这部分没有问题,不能则PWM部分有问题,先改好。
然后调测量的程序。

superid888 发表于 2024-3-7 14:44:59

问题解决没?

飞捷 发表于 2024-3-7 15:46:19

void EEPROM_clean(u8 address)
{
          IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 3;                              //设置IAP擦除命令
    IAP_ADDRL = address;                        //设置IAP低地址
    IAP_ADDRH = address >> 8;                   //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IAP_CONTR = 0;                              //关闭IAP功能
// IAP_CONTR=0x80;                              //源程序eeprom操作
//IAP_ADDRL=address;
//IAP_CMD=0x03;
//IAP_TRIG=0x46;
//IAP_TRIG=0xb9;
}

把每个IAP_TPS = 12;      取消掉,初始化配置一次就好,这个不知有没有影响,我是放初始化执行一次

然后,STC8速度比较快,所以遇到_nop_();    你就多复制几个    _nop_();   _nop_();   _nop_();   _nop_();   
页: [1]
查看完整版本: STC8G1KO8A取代STC15W104中遇到的问题