打印
[STM8]

使用STM8S003F3P6:从Halt唤醒后,有时复位,有时正常,有时几秒

[复制链接]
13668|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qjy_dali|  楼主 | 2013-4-15 11:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
香水城在不?

我们做的产品,以前用的是STM8S103F3P6,后来改用STM8S003F3P6,使用中碰到一些问题,主要有:
  (1)进入halt(非active-halt)后,用IO唤醒,有时候正常,有时候会直接复位(我通过检查复位寄存器,报出的是非法操作码复位),有时候虽能唤醒,但过了好几秒它才醒来。也有极少极少的次数死掉了。
  我的系统中,用了定时器中断做系统滴答,用了UART与主处理器通信,用了ADC检查电池电压等,SPI,EEPROM,I2C均没有用。
  顺便说下,PA1这个变态的IO,我现在的系统中有时候设为普通输入,有时候设为输出,但我没有用它中断(谁用谁知道,人家手册上确实写的很清楚了)

  (2)还有发现过空白的STM8S003F3,在贴片出来后,有个别的Reset引脚上在不断振荡(空白芯片,还没烧代码呢),我外部上拉电阻是4.7K,下拉电容是0.1uF。我尝试去掉上拉,不过一样振。在每5K的生产中,会发现那么几片。

  如方便,请发QQ消息指点下:1260610311。
沙发
IJK| | 2013-4-15 17:21 | 只看该作者
难道是芯片质量问题?

使用特权

评论回复
板凳
qjy_dali|  楼主 | 2013-4-16 13:52 | 只看该作者
通过LED调试进行测试,发现halt后还是正常出来了。只是,在后面执行了一下其它操作后,才发生复位。而复位标志可以查出是“非法操作码”复位。不太明白怎么就会有非法操作码?
有没有快速确认堆栈溢出的方法。我想如果有这种情况,把数据当代码操作,还真是非法操作码了

使用特权

评论回复
地板
IJK| | 2013-4-16 14:49 | 只看该作者
看样子还是LZ的程序有问题,通过LED和示波器调试,应该容易定位问题的

使用特权

评论回复
5
qjy_dali|  楼主 | 2013-4-16 18:28 | 只看该作者
多谢楼上,还在找

使用特权

评论回复
6
qjy_dali|  楼主 | 2013-4-16 18:31 | 只看该作者
比较难找的原因是不能用仿真器,因为SWIM所在的引脚是我的一根按钮输入,所以SWIM上电后禁用;第二,则是因为用了halt模式。

使用特权

评论回复
7
qjy_dali|  楼主 | 2013-4-18 16:50 | 只看该作者
香水城大侠,有空来指点一下:)

使用特权

评论回复
8
IJK| | 2013-4-18 16:52 | 只看该作者
qjy_dali 发表于 2013-4-16 18:31
比较难找的原因是不能用仿真器,因为SWIM所在的引脚是我的一根按钮输入,所以SWIM上电后禁用;第二,则是因 ...

可以通过LED +示波器 来调试

使用特权

评论回复
9
cjhk| | 2013-4-18 18:41 | 只看该作者
呵呵   电子级工程师就是很苦逼的   只能慢慢排查  慢慢解决了   其它还真的就没有办法

使用特权

评论回复
10
cjhk| | 2013-4-18 18:41 | 只看该作者
多试几次   借助网络 多向别人请教      努力   

使用特权

评论回复
11
qjy_dali|  楼主 | 2013-4-18 18:53 | 只看该作者
香水城,请问你们的正规代理商都有哪些?可以在哪里看到?

使用特权

评论回复
12
qjy_dali|  楼主 | 2013-4-22 12:28 | 只看该作者
现在把所有多余的代码都干掉了,只有IO了,一样复位。顺便提一下,用来中断的PD2引脚上有对地的0.1uF电容。

/*
*    器件: STM8S003F3P6
*    工具: IAR for STM8 1.20.1
*/

#include <iostm8s103f3.h>                   // MCU定义

typedef  unsigned char u8;

#define  Enable_IRQ()       asm("RIM")      // 总中断打开
#define  Disable_IRQ()      asm("SIM")      // 总中断禁止
#define  Enter_Wait()       asm("WFI")      // 进入Wait模式
#define  Enter_Halt()       asm("HALT")     // 对应汇编指令HALT
#define  NOP()              asm("NOP")

#define  DLED1_ON()         (PA_ODR_ODR1 = 0)               // Debug-LED1: 亮
#define  DLED1_OFF()        (PA_ODR_ODR1 = 1)               // Debug-LED1: 灭
#define  DLED1_SW()         (PA_ODR_ODR1 = !PA_ODR_ODR1)    // Debug-LED1: 变化

#define  DLED2_ON()         (PC_ODR_ODR5 = 1)               // Debug-LED2: 亮
#define  DLED2_OFF()        (PC_ODR_ODR5 = 0)               // Debug-LED2: 灭
#define  DLED2_SW()         (PC_ODR_ODR5 = !PC_ODR_ODR5)    // Debug-LED2: 变化

#define  DLED3_ON()         (PC_ODR_ODR6 = 1)               // Debug-LED3: 亮
#define  DLED3_OFF()        (PC_ODR_ODR6 = 0)               // Debug-LED3: 灭
#define  DLED3_SW()         (PC_ODR_ODR6 = !PC_ODR_ODR6)    // Debug-LED3: 变化

#define  DLED4_ON()         (PC_ODR_ODR7 = 1)               // Debug-LED4: 亮
#define  DLED4_OFF()        (PC_ODR_ODR7 = 0)               // Debug-LED4: 灭
#define  DLED4_SW()         (PC_ODR_ODR7 = !PC_ODR_ODR7)    // Debug-LED4: 变化

#define  CHG_LED_ON()       (PB_ODR_ODR4 = 0)               // 本机充电指示灯: 亮
#define  CHG_LED_OFF()      (PB_ODR_ODR4 = 1)               // 本机充电指示灯: 灭
#define  CHG_LED_SW()       (PB_ODR_ODR4 = !PB_ODR_ODR4)    // 本机充电指示灯: 变化

#define  FULL_LED_ON()      (PB_ODR_ODR5 = 0)               // 本机充满指示灯: 亮
#define  FULL_LED_OFF()     (PB_ODR_ODR5 = 1)               // 本机充满指示灯: 灭
#define  FULL_LED_SW()      (PB_ODR_ODR5 = !PB_ODR_ODR5)    // 本机充满指示灯: 变化

#define  WakeupKey_IRQ_vector       8                       // PD2端口

void delay(u8 count);
void IO_init(void);
void try_to_halt(void);


/**----------------------------------------------------------------------------------------------*/
void delay(u8 count)
{
    volatile u8 i;
   
    while (count--)
    {
        for (i=235; i!=0; i--);     // 大约1ms? 可以用示波器确认
    }
}


/**----------------------------------------------------------------------------------------------*/
void IO_init(void)
{
    u8 i, reset;
   
    /* 外部中断均为下降沿及低电平中断 */
    EXTI_CR1 = 0x00;
   
   
    /* STM8S103F3P6 PA端口 */
    /* 仅PA1, PA2, PA3有效 */
    PA_ODR = 0x02;      // IO电平初始化
    PA_DDR = 0x0a;      // 配置PA端口的方向寄存器, PA3,1为输出, PA2为输入
    PA_CR1 = 0x0a;      // 设置PA3,1为推挽输出模式, PA2禁用上拉
    PA_CR2 = 0x00;
   
   
    /* STM8S103F3P6 PB端口 */
    /* 仅PB4, PB5有效 */
    PB_ODR = 0x30;      // IO电平初始化
    PB_DDR = 0x30;      // 配置PB端口的方向寄存器PB4-5输出
    PB_CR1 = 0x00;      // 设置PB4,5均为开漏引脚...
    PB_CR2 = 0x00;
   
   
    /* STM8S103F3P6 PC端口 */
    /* 仅PC3-PC7有效 */
    PC_ODR = 0x00;      // IO电平初始化
    PC_DDR = 0xe8;      // 配置PC端口方向寄存器: PC7,PC6,PC5,PC3为输出, PC4为输入(ADC要用)
    PC_CR1 = 0xe8;      // 除PC4外, 全部为推挽输出
    PC_CR2 = 0x00;
   
   
    /* STM8S103F3P6 PD端口 */
    /* 仅PD1-PD6有效 */
    //PD_ODR = 0x00;
    PD_DDR = 0x31;      // 配置PD端口的方向寄存器PD2-3输入, PD6输入(RXD), PD5,PD4输出
    PD_CR1 = 0x32;      // 设置PD5,PD4为推挽, PD3, PD2为悬浮输入(用于ADC), PD1打开上拉
    PD_CR2 = 0x00;
    //PD_ODR = 0x06;
    PD_ODR = 0x00;
   

    /* 复位状态寄存器检查 */
    reset = RST_SR;

   
#if 1
   
    if (reset & 0x01)               // 窗口看门狗复位
    {
        for (i=0; i<20; i++)
        {
            DLED1_SW();
            delay(50);
        }
    }
    else if (reset & 0x02)          // 独立看门狗复位
    {
        for (i=0; i<20; i++)
        {
            DLED2_SW();
            delay(50);
        }
    }
    else if (reset & 0x04)          // 非法操作码复位
    {
        for (i=0; i<20; i++)
        {
            CHG_LED_SW();
            delay(50);
        }
    }
    else if (reset & 0x08)          // SWIM复位
    {
        for (i=0; i<20; i++)
        {
            DLED4_SW();
            delay(50);
        }
    }
    else if (reset & 0x10)          // EMC复位
    {
        for (i=0; i<20; i++)
        {
            DLED3_SW();
            delay(50);
        }
    }
#endif
    RST_SR = 0x1f;      // 写1清0
   
   
    DLED1_ON();                     // LED上电自检
    DLED2_ON();
    DLED3_ON();
    DLED4_ON();
    CHG_LED_ON();
    FULL_LED_ON();
    delay(200);
    delay(200);
    DLED1_OFF();
    DLED2_OFF();
    DLED3_OFF();
    DLED4_OFF();
    CHG_LED_OFF();
    FULL_LED_OFF();
}


/**----------------------------------------------------------------------------------------------*/
void try_to_halt(void)
{
    Disable_IRQ();
   
    //PD_DDR &= ~(0x04);          // PD2确保为输入
    //PD_CR1 &= ~(0x04);          // PD2 禁止上拉

    PD_CR2 |= 0x04;             // PD2设为中断模式, 用于从halt模式唤醒(显示电量按钮&拨动开关)
    DLED2_ON();                 // 调试LED
   
    NOP();
    NOP();
    Enter_Halt();               // 正式进入halt模式!
   
   
    /* 假如突然有事情发生, MCU首先会进对应的唤醒ISR, 然后返回到这里, 开始了新的征程:) */
    NOP();
    NOP();
    Disable_IRQ();              // 需要在中断开启之前重做一下必要的初始化
    DLED2_OFF();                // 调试LED
    //PD_CR2 = 0x00;              // PD中断模式取消,仅做普通输入口
   
    PA_DDR_DDR1 = 1;            // PA1手动更改为输出模式
    PA_CR1_C11  = 1;            // PA1设为推挽模式
    PA_CR2_C21  = 0;
    PA_ODR_ODR1 = 1;            // 低有效的LED控制, 现在先让灯灭
   
    Enable_IRQ();
    NOP();
    NOP();
}


/**----------------------------------------------------------------------------------------------*/
#pragma  vector = WakeupKey_IRQ_vector
__interrupt void ISR_WakeupKey_process(void)
{
    PD_CR2 = 0x00;              // Port-D 中断模式取消,仅做普通输入口
}


/**----------------------------------------------------------------------------------------------*/
int main(void)
{
    delay(20);
    Disable_IRQ();
   
    CPU_CFG_GCR = 0x01;             // 禁用SWIM(即腾出1根IO, 也加强安全性)
    IO_init();                      // IO初始化
    Enable_IRQ();
   
    /* main loop */
    while (1)
    {
        try_to_halt();
    }
}

代码都这样了,一样是非法操作码复位。

使用特权

评论回复
13
qjy_dali|  楼主 | 2013-5-1 18:08 | 只看该作者
各位STM8的高手,多给些指点呀。现在的代码,真真正正是没有用STM8S003F3任何片内外设,只是一个IO的外部中断和Halt,就能出现非法操作码复位。

使用特权

评论回复
14
相耘| | 2013-6-10 17:08 | 只看该作者

非法操作码复位
为了提高设备的可靠性,防止意外行为的发生,使用了非法操作码检测系统。如果一个被执行的代码与任意操作码或预置字节均不相符,则产生一个复位。此功能与看门狗相配合,可使设备从一个意外错误或干扰中恢复。
注意:一个有效的预置字节与一个有效的操作码组成的一个非法的组合将不会产生复位。

使用特权

评论回复
15
zeluo| | 2013-6-10 19:30 | 只看该作者
硬件的故障可能更多一点   个人的理解   楼主  

使用特权

评论回复
16
ccelectric| | 2013-6-16 17:05 | 只看该作者
兄弟 能否给我份基于STM8S003F3P6可以用的程序,IO口能正常, PWM口能出书就行,真不行,IO口正常就行。
我那我103K4的程序配制成STM8S003F3,IO口不正常,PWM口也不正常。可以的话QQ发我 287752762

使用特权

评论回复
17
ccelectric| | 2013-6-16 17:07 | 只看该作者
ccelectric 发表于 2013-6-16 17:05
兄弟 能否给我份基于STM8S003F3P6可以用的程序,IO口能正常, PWM口能出书就行,真不行,IO口正常就行。
我 ...

我的是基于ST Visual Develop的编程软件! 谢谢

使用特权

评论回复
18
shuwei_yz| | 2013-7-12 16:52 | 只看该作者
很有可能是你在外部中断的ISR中取消了PortD的外中断。这句操作语法上没有问题,但是STM8不是STM32,没有后者稳定。
以前看到别人利用STM32的外部中断检测按键时间,也是先设置按键为下降沿触发,然后在外中断ISR中设置成上升沿触发等待按键释放。我按照这个思路移植程序到STM8S平台(STM8S903K3),程序无法运行!

使用特权

评论回复
19
wj19900703| | 2013-7-12 17:46 | 只看该作者
在stm8s的pdf中有这么一句话

当MCU处于停机模式或活跃停机模式时,PA1被自动配置为内部弱上拉并且不可用来唤醒MCU。在这一模式下,PA1无法设置为输出口。在应用中,在停机模式或活跃停机模式下建议将PA1作为输入模式使用。
所以,可能是这个对你的系统产生影响
然后,你的mcu在退出halt模式后延时不够长,因为在halt模式下 主时钟是关闭的,而主时钟从关闭到正常工作肯定不只是两个nop时间,当主时钟异常时,肯定会触发非法代码操作的复位,建议在这里写一个等待主时钟稳定的while循环

使用特权

评论回复
20
侠过留香| | 2015-2-28 14:33 | 只看该作者
楼主解决了吗?我现在是复位加程序卡死在一个地方不动,看看有什么借鉴方法

使用特权

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

本版积分规则

个人签名:------ 美与爱,生活的两大意义 ------ QQ: 1260610311

38

主题

1690

帖子

1

粉丝