OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6087|回复: 16

请教原子兄及各位朋友,谢谢

[复制链接]

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
发表于 2012-7-9 01:46:05 | 显示全部楼层 |阅读模式

我是一个stm32芯片的新手,以前长使用的芯片是AVR的。

学习stm32芯片,就是从原子兄的《不完全手册》开始的,最近做了一个产品,却遇到了一个头疼的问题。

我做的一个产品,平常是休眠(stop模式)的,用户需要使用的时候,就通过一个键盘唤醒系统,唤醒后大概8秒钟未见用户操作的话,系统就再次进入休眠程序。

用户在开始使用我的这个产品的时候,一切正常,但用了大约个把月后,就出现了问题,系统无法唤醒了。程序如下:


void fIntoSleep(void)
{
  fIoIntoSleep();
  fTimerIntoSleep();
  fIntIntoSleep();
  fDmaIntoSleep();
  fDacIntoSleep();
  fUsartIntoSleep();
  fAdcIntoSleep();
  sSys.bSysStatus = 0;
  
  DBGMCU->CR &= ~ (1 << 2); //非调试模式下,standby模式时关闭JTAG接口运行以降低功耗
  DBGMCU->CR &= ~ (1 << 1); //非调试模式下,stop模式时关闭JTAG接口运行以降低功耗
  RCC->CR &= ~ (1 << 0);  //非调试模式下关闭内部RC振荡以降低功耗
//  fSysStandby();
  fSysStop();
  
  //-------------复位------------------
  fCloseIRQHandler();
  fSoftReset();
}

void fIoIntoSleep(void)
{
 //所有IO被配置为模拟输入(省电)
 //PA0  PA1  PA2  PA3  PA4  PA5  PA6  PA7  PA8  PA9  PA10 PA11 PA12 PA13 PA14 PA15
 //I    I    I    I    I    I    I    I    I    I    I    O    O    I    I    I
 //A    A    A    A    A    A    A    A    A    A    A    0    0    A    A    A
 GPIOA->ODR = 0x00000000;
 GPIOA->CRL = 0x00000000;
 GPIOA->CRH = 0x00022220;
 
 //PB0  PB1  PB2  PB3  PB4  PB5  PB6  PB7  PB8  PB9  PB10 PB11 PB12 PB13 PB14 PB15
 //I    I    I    I    O    I    I    I    I    I    I    I    O    O    O    O
 //A    A    T    A    0    P    T    P    P    P    P    P    0    0    0    0
 GPIOB->ODR = 0x00000fa0;
 GPIOB->CRL = 0x84820400;
 GPIOB->CRH = 0x22228888;

 //PC0  PC1  PC2  PC3  PC4  PC5  PC6  PC7  PC8  PC9  PC10 PC11 PC12 PC13 PC14 PC15
 //I    I    I    I    I    I    I    I    I    I    I    I    I    I    I    I
 //A    A    A    A    A    A    A    A    A    A    A    A    A    A    A    A
 GPIOC->ODR = 0x00000000;
 GPIOC->CRL = 0x00000000;
 GPIOC->CRH = 0x00000000;
 
/* RCC->APB2ENR &= ~ (1 << 2);   //portA时钟关闭
 RCC->APB2ENR &= ~ (1 << 3);   //portB时钟关闭
 RCC->APB2ENR &= ~ (1 << 4);   //portC时钟关闭
 RCC->APB2ENR &= ~ (1 << 5);   //portD时钟关闭
 RCC->APB2ENR &= ~ (1 << 0);   //复用功能时钟关闭*/
}

void fTimerIntoSleep(void)
{
 TIM3->CR1 &= ~ (1 << 0); //定时器3关闭
 RCC->APB1RSTR |= 1 << 1;//TIM3复位
 RCC->APB1RSTR &= ~(1 << 1);//复位结束
 RCC->APB1ENR &= ~ (1 << 1);//TIM3 时钟关闭
 
 TIM6->CR1 &= ~ (1 << 0);//TIM6关闭
 RCC->APB1RSTR |= 1 << 4;//TIM6复位
 RCC->APB1RSTR &= ~(1 << 4);//复位结束
 RCC->APB1ENR &= ~ (1 << 4);//TIM6时钟关闭
}

void fIntIntoSleep(void)
{
 RCC->APB2ENR |= 1 << 3; //使能PORTB 时钟
// JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG 和SWD
 GPIOB->ODR &= 0xffff001b;
 GPIOB->ODR |= 0x00000fa0;
 GPIOB->CRL &= 0x000ff0ff;
 GPIOB->CRL |= 0x84800400;
 GPIOB->CRH &= 0x00000000;
 GPIOB->CRH |= 0x22228888;//设置PB2(gSlide)高阻输入、PB5(gLineCtrl)上拉输入、PB6(gDobLock)高阻输入、PB7(gMechKey)上拉输入、PB8(gLatchBolt)上拉输入、PB9、PB10、PB11(Key0、Key1、Key2)上拉输入、PB12、PB13、PB14、PB15(Key3、Key4、Key5、Key6)输出0
 EXTI->FTSR = 0;
 EXTI->FTSR |= 0x00000fe4;//PB2、PB5-11下降沿触发
 EXTI->RTSR = 0;
 EXTI->RTSR |= 0x00000044;//PB2、PB6上升沿触发
 EXTI->IMR = 0;
 AFIO->EXTICR[0] = 0x00000100;
 AFIO->EXTICR[1] = 0x00001110;
 AFIO->EXTICR[2] = 0x00001111;
 EXTI->IMR |= 0x00000fa4;//PB2、PB5-11沿中断打开(PB6反锁功能,不用打开中断)
 fNvicSet(3,3,EXTI0_IRQChannel);//组3,最低优先级
 fNvicSet(3,3,EXTI1_IRQChannel);//组3,最低优先级
 fNvicSet(3,3,EXTI2_IRQChannel);//组3,最低优先级
 fNvicSet(3,3,EXTI3_IRQChannel);//组3,最低优先级
 fNvicSet(3,3,EXTI4_IRQChannel);//组3,最低优先级
 fNvicSet(3,3,EXTI9_5_IRQChannel);//组3,最低优先级
 fNvicSet(3,3,EXTI15_10_IRQChannel);//组3,最低优先级
}

void EXTI0_IRQHandler(void)
{
 EXTI->R |= 1 << 0; //清除LINE0 上的中断标志位
// EXTI->FTSR = 0;
// EXTI->RTSR = 0;
// AFIO->EXTICR[0] = 0;
// AFIO->EXTICR[1] = 0;
// AFIO->EXTICR[2] = 0;
// AFIO->EXTICR[3] = 0;
// EXTI->IMR = 0;
}

void EXTI1_IRQHandler(void)
{
 EXTI->R |= 1 << 1; //清除LINE1 上的中断标志位
// EXTI->FTSR = 0;
// EXTI->RTSR = 0;
// AFIO->EXTICR[0] = 0;
// AFIO->EXTICR[1] = 0;
// AFIO->EXTICR[2] = 0;
// AFIO->EXTICR[3] = 0;
// EXTI->IMR = 0;
}

void EXTI2_IRQHandler(void)
{
 EXTI->R |= 1 << 2; //清除LINE2 上的中断标志位
// EXTI->FTSR = 0;
// EXTI->RTSR = 0;
// AFIO->EXTICR[0] = 0;
// AFIO->EXTICR[1] = 0;
// AFIO->EXTICR[2] = 0;
// AFIO->EXTICR[3] = 0;
// EXTI->IMR = 0;
}

void EXTI4_IRQHandler(void)
{
 EXTI->R |= 1 << 4; //清除LINE4 上的中断标志位
// EXTI->FTSR = 0;
// EXTI->RTSR = 0;
// AFIO->EXTICR[0] = 0;
// AFIO->EXTICR[1] = 0;
// AFIO->EXTICR[2] = 0;
// AFIO->EXTICR[3] = 0;
// EXTI->IMR = 0;
}

void EXTI9_5_IRQHandler(void)
{
 EXTI->R |= 0x0f << 6; //清除LINE6-9 上的中断标志位
// EXTI->FTSR = 0;
// EXTI->RTSR = 0;
// AFIO->EXTICR[0] = 0;
// AFIO->EXTICR[1] = 0;
// AFIO->EXTICR[2] = 0;
// AFIO->EXTICR[3] = 0;
// EXTI->IMR = 0;
}

void EXTI15_10_IRQHandler(void)
{
 EXTI->R |= 0x1f << 10; //清除LINE13 上的中断标志位
// EXTI->FTSR = 0;
// EXTI->RTSR = 0;
// AFIO->EXTICR[0] = 0;
// AFIO->EXTICR[1] = 0;
// AFIO->EXTICR[2] = 0;
// AFIO->EXTICR[3] = 0;
// EXTI->IMR = 0;
}

void fCloseIRQHandler(void)
{
 EXTI->FTSR = 0;
 EXTI->RTSR = 0;
 AFIO->EXTICR[0] = 0;
 AFIO->EXTICR[1] = 0;
 AFIO->EXTICR[2] = 0;
 AFIO->EXTICR[3] = 0;
 EXTI->IMR = 0;
}

void fDmaIntoSleep(void)
{
 DMA1_Channel3->CCR &= ~(1 << 0); //关闭DMA 传输
 RCC->AHBENR &= ~ (1 << 0);//Dma1 时钟关闭
}

void fDacIntoSleep(void)
{
 DAC->CR &= ~ (1 << 0);
 RCC->APB1RSTR |= 1 << 29;//复位DAC接口
 RCC->APB1RSTR &= ~(1 << 29);//复位结束
 RCC->APB1ENR &= ~ (1 << 29);//DAC接口时钟关闭
}

void fUsartIntoSleep(void)
{
 RCC->APB2RSTR |= 1 << 14; //复位串口1
 RCC->APB2RSTR &= ~ (1 << 14);//停止复位
 RCC->APB2ENR &= ~ (1 << 14); //串口1时钟关闭

 RCC->APB1RSTR |= 1 << 17; //复位串口2
 RCC->APB1RSTR &= ~ (1 << 17);//停止复位
 RCC->APB1ENR &= ~ (1 << 17); //串口2时钟关闭
}

void fAdcIntoSleep(void)
{
 ADC1->CR2 &= ~ (1 << 0);
 RCC->APB2RSTR |= 1 << 9; //ADC1 复位
 RCC->APB2RSTR &= ~ (1 << 9);//复位结束
 RCC->APB2ENR &= ~ (1 << 9); //ADC1 时钟关闭
}

//进入待机模式
void fSysStandby(void)
{
 SCB->SCR |= 1 << 2;//使能SLEEPDEEP位 (SYS->CTRL)
   RCC->APB1ENR |= 1 << 28;     //使能电源时钟
  WR->CSR |= 1 << 8;          //设置WKUP用于唤醒
 WR->CR |= 1 << 2;           //清除Wake-up 标志
 WR->CR |= 1 << 1;           //PDDS置位
 __wfi();     //执行WFI指令
}

void fSysStop(void)
{
 SCB->SCR |= 1 << 2;//使能SLEEPDEEP位 (SYS->CTRL)
 RCC->APB1ENR |= 1 << 28;//使能电源时钟
 WR->CR |= 1 << 2;  //清除唤醒位
 PWR->CR |= 1 << 0;  //停机模式下电压调节器处于低功耗模式
 PWR->CR &= ~ (1 << 1); //当CPU进入休眠时,进入停机模式,电压调节器由LPDS位控制
 __wfi();
}

//系统软复位
void fSoftReset(void)
{
 SCB->AIRCR = 0x05FA0000 | (DWORD)0x04;
}


 

//设置每个中断的NVIC,由每个中断初始化函数调用
//bPriorty_NvicInit:抢占优先级
//bSubPriority_NvicInit:响应优先级
//bChannel_NvicInit:中断编号
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//bPriorty_NvicSet和bSubPriority_NvicSe的原则是,数值越小,越优先
//各中断抢占优先级设置根据
//0级:需要尽量实时,且一旦延时,会影响效果的中断,且处理过程特别简单
//1级:需要在较小的一段时间(10us内)内作出处理的中断
//2级:可以在一段时间(100us)内作出处理的中断
//3级:可以在较长时间(10ms)内作出处理的中断
void fNvicSet(BYTE bPriorty_fNvicSet,BYTE bSubPriority_fNvicSet,BYTE bChannel_fNvicSet)
{
 DWORD dTemp_fNvicSet;
 BYTE bIprAdr_fNvicSet = bChannel_fNvicSet / 4;  //每组只能存4个,得到组地址
 BYTE bIprOft_fNvicSet = bChannel_fNvicSet % 4;//在组内的偏移
 
 bIprOft_fNvicSet = bIprOft_fNvicSet * 8 + 4;    //得到偏移的确切位置
 dTemp_fNvicSet = bPriorty_fNvicSet << (4 - mGroupPriorityInit); 
 dTemp_fNvicSet |= bSubPriority_fNvicSet & (0x0f >> mGroupPriorityInit);
 dTemp_fNvicSet &= 0xf;//取低四位
 
 if(bChannel_fNvicSet < 32)
 {
  NVIC->ISER[0] |= 1 << bChannel_fNvicSet;//使能中断位(要清除的话,相反操作就OK)
 }
 else
 {
  NVIC->ISER[1] |= 1 << (bChannel_fNvicSet - 32);
 }
 NVIC->IPR[bIprAdr_fNvicSet] |= dTemp_fNvicSet << bIprOft_fNvicSet;//设置响应优先级和抢断优先级
}


 

另外说明一下,我的中断采用4x4的格式,即4个抢占级,每个抢占级中分4级,堆栈长度是0x00000200。在主程序中(未贴出来)使用的cpu资源如下:usart1(中断模式)、usart2(中断模式)、tim3(中断模式)、tim6(作为dma的时钟)、RTC计数器开启(未开启中断)、ADC开启(未开启中断),主程序中未开启任何外部中断、DMA1(中断模式)、spi1口(扫描模式,未开启中断)、DAC(与DMA组合使用,未开启DAC中断)、systick计数器开启(未开启中断)。

希望能得到原子兄及各位的指点,谢谢大家!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-9 01:54:51 | 显示全部楼层
主晶振采用内部晶振,32K时钟晶振采用贴片圆柱封装,我测量那块板子,发现 fIoIntoSleep()函数已经执行完成了,因为这个函数中有关闭LED和一路3.3V电源的功能,LED已经不亮了,而且那路3。3V电源也已经被切断了。
回复 支持 反对

使用道具 举报

48

主题

376

帖子

0

精华

高级会员

Rank: 4

积分
621
金钱
621
注册时间
2011-3-18
在线时间
7 小时
发表于 2012-7-9 09:15:26 | 显示全部楼层
難醫,要高人先求到了
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-7-9 09:28:22 | 显示全部楼层
你已经可以运行一个多月了,说明之前的代码是无问题的,运行个把月之后出现了问题.
你可以拿2个板子(一个新的,一个有问题的),重刷同样的代码,对比测试一下,看看区别.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-9 14:56:33 | 显示全部楼层
这个问题,并不是只在某一块板上发生过,在几块板上都出现了这种情况。
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-9 15:01:47 | 显示全部楼层
原子兄有没有可能从程序上看出些问题来?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-7-9 15:16:25 | 显示全部楼层
我怀疑可能不是程序问题.硬件问题可能性比较大.
如果程序问题,你应该当时就能测出来的.
所以建议你找一个有问题的板,一个新板,一起刷同样的代码,进行测试.对比.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-10 18:02:37 | 显示全部楼层
我测量了有问题的那块板,功耗竟然是360ua,而正常stop的板,应该是20ua多一点。
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-10 23:38:41 | 显示全部楼层
另外,我按照原子兄的指点,测试了所有IO口的状态,再与工作正常的板子进行了比较,完全一样,只是功耗不同,有问题的板是360ua,没问题的板是21ua。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2012-7-10
在线时间
3 小时
发表于 2012-7-10 23:46:13 | 显示全部楼层
传说中的翻新片?
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-11 00:03:22 | 显示全部楼层
只是偶尔出问题,现在那块板已经重新上电了,重新上电后,一切又都正常了,出问题的就那一次,郁闷。
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-11 00:08:12 | 显示全部楼层
哦,可能我没说清楚,有问题的那块板,也不是说一直有问题,就出那一次问题,复位后或重新上电后,又好了。所谓没问题的那些板呢,也不见得不会出问题,因为我陆续有用户给我反映过一样的问题了。所以我才估计是软件问题,毕竟硬件的偶然性是比较小的,何况我的产品还是5号电池供电的。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-7-11 00:32:27 | 显示全部楼层
回复【12楼】xcfj9412:
---------------------------------
那你这个就比较难查了.
软件问题,只能你自己设定环境,考虑极端情况,进行测试.看看是不是有问题.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-11 14:53:16 | 显示全部楼层
问题已经找到了,我有设置不当的地方,估计芯片也有问题。
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-11 14:54:24 | 显示全部楼层
是时钟的问题,估计是时钟断线了
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-7-9
在线时间
5 小时
 楼主| 发表于 2012-7-11 14:56:18 | 显示全部楼层
晚些时候,等我弄清楚具体的出错的机制,再详细描述。
回复 支持 反对

使用道具 举报

18

主题

82

帖子

0

精华

初级会员

Rank: 2

积分
174
金钱
174
注册时间
2011-10-27
在线时间
0 小时
发表于 2014-11-12 18:53:28 | 显示全部楼层
弄清楚了吗?人呢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-29 06:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表