标签存档: STM32

局部变量使用指针方式赋值可能会导致异常

从协议解析数据是为了提高效率,我常常使用指针直接操作内存地址来替代移位操作,如下 :

    *((u8*)&a+1) = *(pbuf + 0);
    *((u8*)&a+0) = *(pbuf + 1);

继续阅读 »

STM32 要使用一个定时器需要做哪些工作

1.配置该时钟的中断优先级,NVIC
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);     //配置NVIC中断优先级编组
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;  //TIM6中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //抢占优先级1级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
2.初始化该时钟的配置,包括:
开启该定时器的时钟源:RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
清空配置:TIM_DeInit(TIM6);
配置时钟的自动重装计数器:TIM_TimeBaseStructure.TIM_Period=200;
配置时钟源预分频数:TIM_TimeBaseStructure.TIM_Prescaler= (1600 – 1);
配置时钟分频数:TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
配置计数模式:TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
让配置生效:TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
清空溢出中断标志:TIM_ClearFlag(TIM6, TIM_FLAG_Update);
设置溢出中断使能:TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
启动定时器:TIM_Cmd(TIM6, ENABLE);
3.编写该时钟的中断服务函数
void TIM6_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
    {
        TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
        sysClockCount++;                                //用于滚动显示字符
    }
}
来自为知笔记(Wiz)

STM32软件复位(基于V3.5库)

STM32软件复位(基于库文件V3.5)
void SoftReset(void)
{
__set_FAULTMASK(1); // 关闭所有中端
NVIC_SystemReset();// 复位
}

在官方软件库的 core_cm3.h 文件里 直接提供了 系统复位的函数 继续阅读 »

STM32备份域使用示例

  /*系统初始化、配置串口等*/

  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  SerialPutChar(BKP_ReadBackupRegister(BKP_DR9)+'0');
  PWR_BackupAccessCmd(ENABLE);                  /* Enable write access to Backup domain */
  if (BKP_ReadBackupRegister(BKP_DR9))
  {
    BKP_WriteBackupRegister(BKP_DR9,0);
    SerialPutChar(BKP_ReadBackupRegister(BKP_DR9)+'0');
  }
  else
  {
    BKP_WriteBackupRegister(BKP_DR9,1);
    SerialPutChar(BKP_ReadBackupRegister(BKP_DR9)+'0');
  }
  while(1);

执行结果:
首次复位后串口打印01,复位后打印10,每次复位会循环修改。

备份域操作流程:
1.首先, 需要设置RCC_APB1ENR寄存器的PWREN 和 BKPEN位来使能电源和备份域接口时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
2.然后,需要解除备份域的写保护
PWR_BackupAccessCmd(ENABLE);

STM32的systick定时器的详细说明(转)

原文地址:ARM学习《九》——关于STM32的systick定时器的详细说明

转载如下:

我不得不说意法半导体确实有点风骚!甚至有点变态。我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维。手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说。今天我们说的是systick定时器。

systick定时器和我上面说的情况一样,在手册中根本没有介绍。我费了九牛二虎之力才在一个犄角格拉里找到systick定时器的英文版的说明。在Cotex-M3有介绍,为什么要找STM32的介绍,是因为功能设置上还有点区别。首先看一下systick定时器的作用,下面是Cotex-M3里的一段话:

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 继续阅读 »

STM32堆栈溢出引起的问题 变量异常变化且产生Hard Fault

这两天遇到一个很奇怪的问题,在串口通信时串口缓冲区写指针出现异常改变,使用一个vu32的变量累积穿插中断产生的次数,发现该变量变化也异常。并且最终导致Hard_Fault。

一开始怀疑是数组越界,仔细检查没有发现数组访问越界的问题;后来怀疑是系统时钟配置或NVIC配置异常,检查后也没发现问题。

最后整理代码,删掉main函数开始的一个500字节的数组定义(该数组并没有使用到),程序恢复正常。

检查工程的linker配置,发现stack(栈)配置为0x0800(2048)Bytes,heap(堆)配置为0x0200(512)Bytes,所以在main函数中定义500字节数组很可能导致程序运行时堆空间溢出了。

Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement

Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement EW targets: All EW component: C/C++ compiler Keywords: C code, keywords, SFR, UART Last update: January 14, 2009 Background The warning [Pa082] is issued if 2 (or more) of the variables in a C-statment are volatile. The message text “…order of volatile accesses is undefined…” is the central information, i.e. the compiler (following the ANSII standard) can access the variables in an order that is not defined. Is this a problem , or not… …well that depends on your application. Volatile is (typically) used for variables that are accessed from several threads in the application, and for Special Function Register that are the connection in/out of the chip. So you must study the volatile variables that are present in this C-statement and from the usage of these volatile variables decide if you must make a change or not. How to change The change is to break up the C-statement, so that each new C-statement holds only one access to a volatile variable. In this small example the variables internalChannelSelect and ADC are volatile. If so the following C-source will issue the “Warning[Pa082]”. intAnalogSample[internalChannelSelect] = ADC[internalChannelSelect] ; Then the following change will make the C-source predictable. i = internalChannelSelect; k = ADC; intAnalogSample = k;

STM32时钟控制RCC探究

本文转自百度文库,作者不详,感谢原作者的分享和总结!
RTC是STM32单片机的脉搏,是单片机的驱动源。使用任何一个外设都必须打开相应的时钟。这样的好处就是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果。

STM32单片机的时钟可以由以下3个时钟源提供:

1、HSI:高速内部时钟信号 stm32单片机内带的时钟 (8M频率) 精度较差

2、HSE:高速外部时钟信号 精度高 来源(1)HSE外部晶体/陶瓷谐振器(晶振) (2)HSE用户外部时钟

3、LSE:低速外部晶体 32.768kHz 主要提供一个精确的时钟源 一般作为RTC时钟使用

stm32单片机的将时钟信号(例如HSE)经过分频或倍频(PLL)后,得到系统时钟,系统时钟经过分频,产生外设所使用的时钟。 继续阅读 »

第 1 页,共 3 页123