现在把所有多余的代码都干掉了,只有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();
}
}
代码都这样了,一样是非法操作码复位。 |