27,377
社区成员
stm8L152C6开发板两个诡异问题:1,RTC时钟,秒针走,分针不走;2,按键中断就死机。
1、RTC时钟配置中,秒针走时正常,但是到60s,分钟不动?这是怎么回事?
2、设置了PB0作为按键中断,中断触发为下降沿和低电平触发。但是一按按键PB0,程序就不走了,也不会到main程序。在IAR程序中,一直处在__iar_unhandled_exception 008985 9D 008986 20FD 。
#include"iostm8l052c6.h"
#include"stdint.h"
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
//typedef unsigned char uint8_t;
//typedef unsigned short uint16_t;
//typedef unsigned long uint32_t;
#define KEY1 PB_IDR_IDR0
//==================定义常数=====================//
#define a 0x01
#define b 0x02
#define c 0x04
#define d 0x08
#define e 0x10
#define f 0x20
#define g 0x40
#define m 0x80
const uint16_t NumberMap[10]=
{
a+b+c+d+e+f, // Display "0"
b+c, // Display "1"
a + b + m + g + e + d, // Displays "2"
a + b + m + g + c + d, // Displays "3"
f + g + m + b + c, // Displays "4"
a + f + g + m + c +d, // Displays "5"
a + f + e + d + c + g + m , // Displays "6"
a + b + c, // Displays "7"
a + b + c + d + e + f + g + m, // Displays "8"
a + b + c + d + f + g + m // Displays "9"
};
void system_init(void);
void GPIO_Init(void);
void LCD_Config(void);
void RTC_Config(void);
void LCD_GLASS_Clear(void);
void LCD_GLASS_Confirm(void);
void LCD_DisplayNum(uint16_t Num);
void Delay(u16 Second);
void system_init(void)
{
if(CLK_SCSR!=0x01)
{
CLK_SWCR |= 0x02;//使能自动时钟切换
CLK_SWR = 0x01; //HSI为主时钟源
while(!CLK_SWCR_SWIF);
//CLK_CKDIVR = 0x00;//CPU时钟0分频,系统时钟0分频
CLK_SWCR = 0;
}
CLK_CSSR = 0x01;//时钟安全监测使能
CLK_PCKENR2_PCKEN20 = 1; //打开ADC1时钟
CLK_PCKENR2_PCKEN22 = 1; //打开RTC时钟,LCD刷新频率与此有关
CLK_PCKENR2_PCKEN23 = 1; //打开LCD时钟,读写LCD寄存器用到此时钟
CLK_CRTCR = 0x10; //set RTC division favter[7:5] and clock source [4:1]
//CLK_CRTCR: Clock RTC register; 前3位为时钟分频值,后4位为时钟选择位,
//最后一位为系统忙标志位
}
void RTC_Config(void)
{
RTC_WPR = 0xCA; //disable write protection
RTC_WPR = 0x53;
RTC_ISR1_INIT = 1; //initialize
while(!RTC_ISR1_INITF);
//初始化时间与日期
RTC_TR1_ST=5; // second tens RTC_TR1 (second)
RTC_TR1_SU=5; // second units
RTC_TR2_MNT=4; // minute tens RTC_TR2 (minute)
RTC_TR2_MNU=2; // minute units
RTC_TR3_PM=0; // AM/PM
RTC_TR3_HT=1; // Hour tens
RTC_TR3_HU=1; // hour units
RTC_DR1_DT=2; // date tens
RTC_DR1_DU=6; // date units
RTC_DR2_WDU=1; // week day units
RTC_DR2_MT=0; // month tens
RTC_DR2_MU=9; // month units
RTC_DR3_YT=1; // year tens
RTC_DR3_YU=6; // year units
RTC_CR1 |=0x40; // 24 hour
//RTC_CR1_BYPSHAD=1;
RTC_APRER=0x7F; //保持默认值0x7F,异步RTC寄存器
RTC_SPRERH=0x00;
RTC_SPRERL=0xFF; //保持默认值0xFF,同步RTC寄存器
//以上两个RTC时钟分频值保持默认
//最终提供给日历模块的时钟为32768Hz/((127+1)*(255+1))=1
RTC_ISR1_INIT=0; //退出初始化模式
RTC_CR2_ALRAE=0; //disable the alarm
RTC_WPR=0x55;//使能写保护
RTC_WPR=0x55;
}
void GPIO_Init(void)
{
//**********Key 输入***************//
EXTI_CR1=0xE4;
ITC_SPR2=0x73;
PB_DDR_DDR0 = 0; //PB[0:4]端口为输入端口
PB_CR1_C10 = 1; //上拉输入
PB_CR2_C20 = 1; //使能中断:1
}
void LCD_Config(void)
{
LCD_FRQ = 0x00; //Frequency selectrion register (PS and DIV)
LCD_CR1 = 0x06; // control register 1: set blink, blink frequency,
// duty ratio, bias.
LCD_CR2 = 0xFE; // control register 2: set pulse on duation,
// high drive enable, contrast control
/*-----------Mask register----------------*/
LCD_PM0 = 0xFF; // Seg[7:0] enable
//LCD_PM1 = 0x00; // Seg[8:15] enable
LCD_PM2 = 0xFF; // Seg[16:23] enable
//LCD_PM3 = 0x00; // Seg[24:31] enable
LCD_CR3 = 0x40; // control register 3: set LCD enable, interrupt enable,
// frame flag, SOD flag, Dead time enable
}
//********************LCD 清零**********************************//
void LCD_GLASS_Clear(void)
{
LCD_RAM0 = 0x00;
LCD_RAM1 = 0x00;
LCD_RAM2 = 0x00;
LCD_RAM3 = 0x00;
LCD_RAM4 = 0x00;
LCD_RAM5 = 0x00;
LCD_RAM6 = 0x00;
LCD_RAM7 = 0x00;
LCD_RAM8 = 0x00;
LCD_RAM9 = 0x00;
LCD_RAM10 = 0x00;
LCD_RAM11 = 0x00;
LCD_RAM12 = 0x00;
LCD_RAM13 = 0x00;
}
void LCD_GLASS_Confirm(void)
{
LCD_RAM0 = 0xFF;
LCD_RAM1 = 0xFF;
LCD_RAM2 = 0xFF;
LCD_RAM3 = 0xFF;
LCD_RAM4 = 0xFF;
LCD_RAM5 = 0xFF;
LCD_RAM6 = 0xFF;
LCD_RAM7 = 0xFF;
LCD_RAM8 = 0xFF;
LCD_RAM9 = 0xFF;
LCD_RAM10 = 0xFF;
LCD_RAM11 = 0xFF;
LCD_RAM12 = 0xFF;
LCD_RAM13 = 0xFF;
}
void LCD_DisplayNum(uint16_t Num)
{
uint8_t tmp=0;
//tmp=NumberMap[Num];
uint8_t wei=4;
switch(wei)
{
case 4:
tmp=NumberMap[Num%10000/1000];
((tmp&a)==0)?(LCD_RAM6 &= (~0x04)):(LCD_RAM6 |= 0x04); //1A
((tmp&b)==0)?(LCD_RAM2 &= (~0x40)):(LCD_RAM2 |= 0x40); //1B
((tmp&c)==0)?(LCD_RAM3 &= (~0x20)):(LCD_RAM3 |= 0x20); //1C
((tmp&d)==0)?(LCD_RAM3 &= (~0x10)):(LCD_RAM3 |= 0x10); //1D
((tmp&e)==0)?(LCD_RAM0 &= (~0x01)):(LCD_RAM0 |= 0x01); //1E
((tmp&f)==0)?(LCD_RAM6 &= (~0x08)):(LCD_RAM6 |= 0x08); //1F
((tmp&g)==0)?(LCD_RAM2 &= (~0x80)):(LCD_RAM2 |= 0x80); //1G
((tmp&m)==0)?(LCD_RAM0 &= (~0x02)):(LCD_RAM0 |= 0x02); //1M
case 3:
tmp=NumberMap[Num%1000/100];
((tmp&a)==0)?(LCD_RAM6 &= (~0x01)):(LCD_RAM6 |= 0x01); //2A
((tmp&b)==0)?(LCD_RAM2 &= (~0x10)):(LCD_RAM2 |= 0x10); //2B
((tmp&c)==0)?(LCD_RAM3 &= (~0x80)):(LCD_RAM3 |= 0x80); //2C
((tmp&d)==0)?(LCD_RAM3 &= (~0x40)):(LCD_RAM3 |= 0x40); //2D
((tmp&e)==0)?(LCD_RAM0 &= (~0x04)):(LCD_RAM0 |= 0x04); //2E
((tmp&f)==0)?(LCD_RAM6 &= (~0x02)):(LCD_RAM6 |= 0x02); //2F
((tmp&g)==0)?(LCD_RAM2 &= (~0x20)):(LCD_RAM2 |= 0x20); //2G
((tmp&m)==0)?(LCD_RAM0 &= (~0x08)):(LCD_RAM0 |= 0x08); //2M
LCD_RAM7 |= 0x08; //2colon
case 2:
tmp=NumberMap[Num%100/10];
((tmp&a)==0)?(LCD_RAM5&=~0x40):(LCD_RAM5 |=0x40) ;
((tmp&b)==0)?(LCD_RAM2&=~0x04):(LCD_RAM2 |=0x04) ;
((tmp&c)==0)?(LCD_RAM4&=~0x02):(LCD_RAM4 |=0x02) ;
((tmp&d)==0)?(LCD_RAM4&=~0x01):(LCD_RAM4 |=0x01) ;
((tmp&e)==0)?(LCD_RAM0&=~0x10):(LCD_RAM0 |=0x10) ;
((tmp&f)==0)?(LCD_RAM5&=~0x80):(LCD_RAM5 |=0x80) ;
((tmp&g)==0)?(LCD_RAM2&=~0x08):(LCD_RAM2 |=0x08) ;
((tmp&m)==0)?(LCD_RAM0&=~0x20):(LCD_RAM0 |=0x20) ;
case 1:
tmp=NumberMap[Num%10/1];
((tmp&a)==0)?(LCD_RAM5&=~0x10):(LCD_RAM5 |=0x10) ;
((tmp&b)==0)?(LCD_RAM2&=~0x01):(LCD_RAM2 |=0x01) ;
((tmp&c)==0)?(LCD_RAM4&=~0x08):(LCD_RAM4 |=0x08) ;
((tmp&d)==0)?(LCD_RAM4&=~0x04):(LCD_RAM4 |=0x04) ;
((tmp&e)==0)?(LCD_RAM0&=~0x40):(LCD_RAM0 |=0x40) ;
((tmp&f)==0)?(LCD_RAM5&=~0x20):(LCD_RAM5 |=0x20) ;
((tmp&g)==0)?(LCD_RAM2&=~0x02):(LCD_RAM2 |=0x02) ;
((tmp&m)==0)?(LCD_RAM0&=~0x80):(LCD_RAM0 |=0x80) ;
break;
default:break;
}
}
void Delay(u16 Second)
{
u8 i,j;
while(Second--)
{
for(i=0;i<50;i++)
for(j=0;j<50;j++);
}
}
void main(void)
{
u16 H_shi=0,H_ge=0,M_shi=0,M_ge=0,S_shi=0,S_ge=0;
u8 count=0,count_shi=0,count_bai=0,count_qian=0;
asm("sim");
system_init();
GPIO_Init();
LCD_Config();
RTC_Config();
LCD_GLASS_Clear();
LCD_GLASS_Confirm();
LCD_GLASS_Clear();
asm("rim");
/*************************************************************/
while(1)
{
LED3 = 1;
while(!RTC_ISR1_RSF);
S_ge = (u16)RTC_TR1_SU;
S_shi = (u16)RTC_TR1_ST;
M_ge = (u16)RTC_TR2_MNU;
M_shi = (u16)RTC_TR2_MNT;
H_ge = (u16)RTC_TR3_HU;
H_shi = (u16)RTC_TR3_HT;
RTC_ISR1_RSF=0;
LCD_DisplayNum(M_shi*1000+M_ge*100+S_shi*10+S_ge);
}
#pragma vector=0x06
__interrupt void EXTI_PORTB_IRQHandler(void)
{
LCD_DisplayNum(100);
LED_Discovery1=!LED_Discovery1;
//EXTI_SR1=0xFF;
//EXTI_SR2=0xFF;
//return;
}
请问可以加个联系方式嘛大佬,有不懂的问题想咨询
第二个问题也解决了。需要读取RTC_DR3_YT和RTC_DR3_HU的数据,然后计时就正常了。
第二个问题解决了,是中断向量写错了。
出现这个问题的主要原因是参考的书本(stm8单片机入门、进阶与应用实例)和STM8L152C4TDatasheet,RM0031_stm8l050文档的中断向量定义不一致。书本中PB IO端口的外部中断#pramga vector = 0x06。但是Datasheet上的Interrupt mapping给出的Px0引脚的中断向量应为(8+2)EXTI0,其中x代表A,B,C,D端口。
RM0031没有给出中断向量图,需要到STM8L152Datasheet中找。
书本给出的是STM8S207、208系列单片机,我的开发板是8L152的单片机,两者有很大的差别。
但是时钟问题还是没有解决,为什么分钟不走呢?诡异的是,我设定分钟初始值为42,程序跑时偶尔会出现分钟变为43,但是接着就不会再改变了。