声明
#include "STM8S103F2P.h"
#define uint unsigned int
#define uchar unsigned char
#define NGI() _asm("sim"); /* 禁止全局中断 */
#define EGI() _asm("rim"); /* 使能全局中断 */
#define BitSet(a,b) (a |= (1<
#define BitClr(a,b) (a &= ~(1<
#define BitCpl(a,b) (a^=1<
#define GetBit(a,b) (((a)>>(b))&0X01)/* 获取变量a第b位 */
stm8_interrupt.c
#include "lt101.h"
void Sun_check(void);
//void light_control(void);
typedef void @far (*interrupt_handler_t)(void);
struct interrupt_vector {
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
@far @interrupt void PORTA_Interrupt_IRQHandler (void)
{
key_bit=1;//标志位
}
@far @interrupt void TIM4_UPD_OVF_IRQHandler (void)
{
minisecond++; //10ms
TIM4_SR &= 0xFE;
if((key_bit==1)&&(GetBit(PA_IDR,3))==0)//按键按下 并且处于低电平
{
counter++; //counter10ms加一次,由此值判断长按短按
}
return;
}
extern void _stext(); /* startup routine */
struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext}, /* reset */
{0x82, NonHandledInterrupt}, /* trap */
{0x82, NonHandledInterrupt}, /* irq0 */
{0x82, NonHandledInterrupt}, /* irq1 */
{0x82, NonHandledInterrupt}, /* irq2 */
{0x82, PORTA_Interrupt_IRQHandler}, /* irq3 */
{0x82, NonHandledInterrupt}, /* irq4 */
{0x82, NonHandledInterrupt}, /* irq5 */
{0x82, NonHandledInterrupt}, /* irq6 */
{0x82, NonHandledInterrupt}, /* irq7 */
{0x82, NonHandledInterrupt}, /* irq8 */
{0x82, NonHandledInterrupt}, /* irq9 */
{0x82, NonHandledInterrupt}, /* irq10 */
{0x82, NonHandledInterrupt}, /* irq11 */
{0x82, NonHandledInterrupt}, /* irq12 */
{0x82, NonHandledInterrupt}, /* irq13 */
{0x82, NonHandledInterrupt}, /* irq14 */
{0x82, NonHandledInterrupt}, /* irq15 */
{0x82, NonHandledInterrupt}, /* irq16 */
{0x82, NonHandledInterrupt}, /* irq17 */
{0x82, NonHandledInterrupt}, /* irq18 */
{0x82, NonHandledInterrupt}, /* irq19 */
{0x82, NonHandledInterrupt}, /* irq20 */
{0x82, NonHandledInterrupt}, /* irq21 */
{0x82, NonHandledInterrupt}, /* irq22 */
{0x82, TIM4_UPD_OVF_IRQHandler}, /* irq23 */
{0x82, NonHandledInterrupt}, /* irq24 */
{0x82, NonHandledInterrupt}, /* irq25 */
{0x82, NonHandledInterrupt}, /* irq26 */
{0x82, NonHandledInterrupt}, /* irq27 */
{0x82, NonHandledInterrupt}, /* irq28 */
{0x82, NonHandledInterrupt}, /* irq29 */
};
MAIN.c
/***************************************************************
**************长按进入停机模式,短按开机*********************
****************************************************************
*******/
//过放电路由硬件实现
#include "lt101.h"
#include "cpu_init.h"
void Sun_check(void); //电压采样
void Free_WWDG(void); //窗口看门狗
void light_control(void); //闪烁控制函数
uint minisecond; //light_control 函数用到的light
uint counter=0;
uchar sun=0;
uchar work_state=0; //等于0时工作,1时停止工作
uint cycle= 100; //灯亮灭周期时间1s
uchar lighting_time= 15; //灯亮持续时间150ms
uchar key_mode=0; //按键模式
uchar key_bit=0; //标志位
main()
{
NGI(); /*禁止中断*/
CLK_Init(); /*时钟初始化*/
GPIO_Init(); /*端口初始化*/
EXTI_Init();/*外部中断触发方式*/
Tim4_Init();/*定时器初始化*/
ADC_Init();
WWDG_Init(); /*窗口看门狗初始化*/
EGI();
while (1)
{
Free_WWDG(); /*喂狗*/
Sun_check(); /*ADC采样*/
light_control(); /*灯闪烁程序*/if(counter>300) /*判断按键按下大于3S*/
{
Free_WWDG(); /*喂狗*/
counter=0; /*清空计数*/
key_bit=0; /*清空标志位*/
BitClr(PC_ODR,6); /*清空按键*/
key_mode=0; /*清空按键*/
_asm("halt"); /*进入到低功耗模式*/
FLASH_CR1 = 0x080;
}
if((counter>100)&&(counter<200))/*若按键按下1-2s*/
{
Sun_check();
light_control();
}
}
}/***************************************************************
************** ADC 采样 用来判断白天黑夜的**********************
***************************************************************/
void Sun_check(void)
{
unsigned char i;
unsigned int AD_Value;
ADC_CSR = 0x05;//选择通道AIN5
ADC_CR1 |= 0x01; /* First set ADON to power on the ADC module. */
i = 12; /* Wait >7us to ensure the ADC power on finished.*/
while(i--);
ADC_CR1 |= 0x01; /* Set ADON again to start AD convert. */
while(!(ADC_CSR & 0x80));/* Waiting for AD convert finished (EOP=1). */
AD_Value = ((((unsigned int)ADC_DRH)<<2)+ADC_DRL);
if(AD_Value > 25)
sun = 1;
if(AD_Value < 20)
sun = 0;
}
/****************************************************************
*********************灯闪烁控制**********************************
*****************************************************************
****************************************************************/
void light_control(void)
{
if(sun == 0)
{
if(minisecond <= lighting_time)
{
BitSet(PC_ODR,6);//输出高电平,灯亮持续时间lighting_time}
if(minisecond > lighting_time)
{
BitClr(PC_ODR,6); //输出低电平,灯灭
}
if(minisecond > cycle) //周期时间cycle
{
Sun_check();minisecond = 0;
}
}
if(sun == 1) //检测到白天
{
if(minisecond > 100)
{
BitClr(PC_ODR,6); //输出低电平
Sun_check();minisecond = 0;
}
}
}
/****************wwdg**************
*************窗口看门狗——喂狗程序**************
***********************************/
void Free_WWDG(void)
{
if((WWDG_CR&0X7F)<=WWDG_WR)//小于窗口值才能喂狗
WWDG_CR|=0X7F; //重新喂狗
}
初始化函数
#include "cpu_init.h"
void CLK_Init(void)
{
// CLK_ICKR = 0X08;//enable LSI
CLK_SWCR = CLK_SWCR | 0x02; // SWEN = 1
CLK_SWR = 0XD2;//chose LSI 128K
while((CLK_SWCR & 0x08) == 0); // 等待切换成功
CLK_SWCR = CLK_SWCR & 0xFD; // 清除切换
CLK_CKDIVR = 0X00; //Fmaster=128KHZ, Fcpu=128KHZ/128=1k
CLK_PCKENR1 = 0x10;//T4
CLK_PCKENR2 = 0x08;//ADC
}
void GPIO_Init(void)
{
/*PA3:KEY */
BitClr(PA_DDR,3); //PA3 Input.
BitSet(PA_CR1,3); //
BitSet(PA_CR2,3); //Enable extern interrupt
/*PC3:KEY */
BitSet(PC_DDR,3); //PC3 Output.
BitSet(PC_CR1,3); //pull up
BitClr(PC_CR2,6); //
/*PC6
OUT*/
BitSet(PC_DDR,6); //PC6 Output.
BitSet(PC_CR1,6); //pull up
BitClr(PC_CR2,6); //
/*PD5:ADC */
BitClr(PD_DDR,5); //PD5 Input. .
BitClr(PD_CR1,5); //
BitClr(PD_CR2,5); //Output speed up to 2MHz.
}
void Tim4_Init(void)
{
TIM4_IER = 0x00;
TIM4_EGR = 0x01;
TIM4_PSCR =0x03;//128k/8
TIM4_CNTR =0;
TIM4_ARR =160;
TIM4_CR1 = 0x01;
TIM4_SR &= 0xFE;
TIM4_IER = 0x01;
}
void ADC_Init(void)
{
ADC_CR2 = 0x00;
ADC_CR1 = 0x00;
ADC_TDRL = 0x20;
}
void WWDG_Init(void)
{
//窗口看门狗在计数值降到0x3f时产生复位,而且不能在大于窗口值时喂狗。
//否则复位
WWDG_WR=0x60; //看门狗窗口值,窗口值必须在0x3F以上,但必须小于计数值,否则无法喂狗
WWDG_CR=0x7F; //看门狗计数值
WWDG_CR|=0x80; //使能窗口看门狗
// 128k主频,计数值0x7F 最大延长时间为 (64 * (12288 / 128000)) = 6.14s
//看门狗
}
void EXTI_Init(void)
{
EXTI_CR1=0X02;//PA口下降沿触发
}