zoukankan      html  css  js  c++  java
  • STM32外设使用要点

    ========================== Reset/Clock Control ======================= 
    1、时钟安全系统(CSS) 
       时钟安全系统被激活后,时钟监控器将实时监控外部高速振荡器;如果HSE时钟发生故障,外部振荡器自动被关闭,产生时钟安全中断,该中断被连接到Cortex-M3的NMI的中断;同时CSS将内部RC振荡器切换为STM32的系统时钟源(对于STM32F103,时钟失效事件还将被送到高级定时器TIM1的刹车输入端,用以实现电机保护控制)。 
       操作流程: 
       1)、启动时钟安全系统CSS:   RCC_ClockSecuritySystemCmd(ENABLE); (NMI中断是不可屏蔽的!) 

       2)外部振荡器失效时,产生NMI中断,对应的中断程序: 
        void NMIException(void) 
        { 
          if (RCC_GetITStatus(RCC_IT_CSS) != RESET) 
            {      // HSE、PLL已被禁止(但是PLL设置未变) 
              …… // 客户添加相应的系统保护代码处 
                   // 下面为HSE恢复后的预设置代码 
              RCC_HSEConfig(RCC_HSE_ON);           // 使能HSE 
              RCC_ITConfig(RCC_IT_HSERDY, ENABLE); // 使能HSE就绪中断 
              RCC_ITConfig(RCC_IT_PLLRDY, ENABLE); // 使能PLL就绪中断 
              RCC_ClearITPendingBit(RCC_IT_CSS);   // 清除时钟安全系统中断的挂起位 
              // 至此,一旦HSE时钟恢复,将发生HSERDY中断,在RCC中断处理程序里, 系统时钟可以设置到以前的状态 
            } 
        } 

       3)、在RCC的中断处理程序中,再对HSE和PLL进行相应的处理。 

    注意:一旦CSS被激活,当HSE时钟出现故障时将产生CSS中断,同时自动产生 NMI。NMI将被不断执行,直到CSS中断挂起位被清除。因此,在NMI的处理程序中 必须通过设置时钟中断寄存器(RCC_CIR)里的CSSC位来清除CSS中断。 

    2、SysTick工作原理 
       Cortex-M3的内核中包含一个SysTick时钟。SysTick 为一个24位递减计数器,SysTick设定初值并使能后, 每经过1个系统时钟周期,计数值就减1。计数到0时, SysTick计数器自动重装初值并继续计数,同时内部的 COUNTFLAG标志会置位,触发中断(如果中断使能)。 


    3、内部时钟输出PA.8(MCO) 
       STM32的PA.8引脚具有复用功能——时钟输出(MCO), 该功能能将STM32内部的时钟通过PA.8输出. 
       操作流程: 
       1)、设置PA.8为复用Push-Pull模式。 
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
        GPIO_Init(GPIOA, &GPIO_InitStructure); 

       2)、选择输出时钟源。 
        时钟的选择由时钟配置寄存器(RCC_CFGR)中的MCO[2:0]位控制。 
        RCC_MCOConfig(RCC_MCO); 
        参数RCC_MCO为要输出的内部时钟: 
          RCC_MCO_NoClock --- 无时钟输出 
          RCC_MCO_SYSCLK --- 输出系统时钟(SysCLK) 
          RCC_MCO_HSI --- 输出内部高速8MHz的RC振荡器的时钟(HSI) 
          RCC_MCO_HSE --- 输出高速外部时钟信号(HSE) 
          RCC_MCO_PLLCLK_Div2 --- 输出PLL倍频后的二分频时钟(PLLCLK/2) 

    注:由于STM32 GPIO输出管脚的最大响应频率为50MHz,如果输出频率超过50MHz,则输出的波形会失真。 

    4、可编程电压监测器(PVD) 
       STM32内部自带PVD功能,用于对MCU供电电压VDD进行监控。通过电源控制寄存器中的PLS[2:0]位可以用来设定监控电压的阀值,通过对外部电压进行比较来监控电源。当条件触发,需要系统进入特别保护状态,执行紧急关闭任务:对系统的一些数据保存起来,同时对外设进行相应的保护操作。 
       操作流程: 
        1)、系统启动后启动PVD,并开启相应的中断。 
        PWR_PVDLevelConfig(PWR_PVDLevel_2V8); // 设定监控阀值  
        PWR_PVDCmd(ENABLE); // 使能PVD  
        EXTI_StructInit(&EXTI_InitStructure);  
        EXTI_InitStructure.EXTI_Line = EXTI_Line16; // PVD连接到中断线16上  
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //使用中断模式  
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Raising;//电压低于阀值时产生中断  
        EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能中断线  
        EXTI_Init(&EXTI_InitStructure); // 初始 
           EXTI_InitStructure.EXTI_Trigger的赋值可选项: 
                  EXTI_Trigger_Rising---表示电压从高下降到低于设定阀值时产生中断; 
           EXTI_Trigger_Falling---表示电压从低上升到高于设定阀值时产生中断; 
                  EXTI_Trigger_Rising_Falling---表示电压上升或下降越过设定阀值时都产生中断。 

        2)、当工作电压低于设定阀值时,将产生PVD中断,在中断程序中进行相应的处理: 
        void PVD_IRQHandler(void)  
        { 
          EXTI_ClearITPendingBit(EXTI_Line16); 
          …… // 用户添加紧急处理代码处 
        } 

    5、STM32上不使用外部晶振,OSC_IN和OSC_OUT的接法  
       1)、对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。 
       2)、对于少于100脚的产品,有2种接法: 
         2.1)、OSC_IN和OSC_OUT分别通过10K电阻接地。 
               此方法可提高EMC性能。 
         2.2)、分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。 
               此方法可以减小功耗并(相对上面2.1),并节省2个外部电阻。 


    ============================ Interrupt/Evens ========================= 
    1、NVIC的优先级概念 
       占先式优先级 (pre-emption priority): 
       高占先式优先级的中断事件会打断当前的主程序/中断程序运行— —抢断式优先响应,俗称中断嵌套。 

       副优先级(subpriority): 
       在占先式优先级相同的情况下,高副优先级的中断优先被响应; 
       在占先式优先级相同的情况下,如果有低副优先级中断正在执行, 高副优先级的中断要等待已被响应的低副优先级中断执行结束后才 能得到响应——非抢断式响应(不能嵌套)。 

    2、判断中断是否会被响应的依据 
        首先是占先式优先级,其次是副优先级; 
        占先式优先级决定是否会有中断嵌套; 
        Reset、NMI、Hard Fault 优先级为负(高于普通中断优先级)且不可调整。 

    3、STM32中用到的Cortex-M3寄存器说明 
       在STM32中用到了Cortex-M3定义的三组寄存器,有关这三组寄存器的说明不在STM32的技术手册中,需要参考ARM公司发布的Cortex-M3 Technical Reference Manual (r2p0)。 
       在STM32的固件库中定义了三个结构体与这三个寄存器组相对应,这三个结构体与ARM手册中寄存器的对应关系如下: 

       1)、NVIC寄存器组 
           STM32的固件库中有如下定义: 
           typedef struct 
           { 
             vu32 ISER[2]; 
             u32 RESERVED0[30]; 
             vu32 ICER[2]; 
             u32 RSERVED1[30]; 
             vu32 ISPR[2]; 
             u32 RESERVED2[30]; 
             vu32 ICPR[2]; 
             u32 RESERVED3[30]; 
             vu32 IABR[2]; 
             u32 RESERVED4[62]; 
             vu32 IPR[11]; 
           } NVIC_TypeDef; 

           它们对应ARM手册中的名称为 
           ISER = Interrupt Set-Enable Registers 
           ICER = Interrupt Clear-Enable Registers 
           ISPR = Interrupt Set-Pending Register 
           ICPR = Interrupt Clear-Pending Register 
           IABR = Active Bit Register 
           IPR = Interrupt Priority Registers 

           每个寄存器有240位,以Interrupt Set-Enable Registers说明,ISER[0]对应中断源0~31,ISER[1]对应中断源32~63,STM32只有60个中断源,所以没有ISER[2:7]。 

           参考STM32技术参考手册中的中断向量表,中断源的位置为: 
           位置0 - WWDG = Window Watchdog interrupt 
           位置1 - PVD = PVD through EXTI Line detection interrupt 
           位置2 - TAMPER = Tamper interrupt 
           ...... 
           位置58 - DMA2_Channel3 = DMA2 Channel3 global interrupt 
           位置59 - DMA2_Channel4_5 = DMA2 Channel4 and DMA2 Channel5 global interrupts 

      
       2)、系统控制寄存器组 
           STM32的固件库中有如下定义: 
           typedef struct 
           { 
             vuc32 CPUID; 
             vu32 ICSR; 
             vu32 VTOR; 
             vu32 AIRCR; 
             vu32 SCR; 
             vu32 CCR; 
             vu32 SHPR[3]; 
             vu32 SHCSR; 
             vu32 CFSR; 
             vu32 HFSR; 
             vu32 DFSR; 
             vu32 MMFAR; 
             vu32 BFAR; 
             vu32 AFSR; 
           } SCB_TypeDef; /* System Control Block Structure */ 
            
           它们对应ARM手册中的名称为 
           CPUID = CPUID Base Register 
           ICSR = Interrupt Control State Register 
           VTOR = Vector Table Offset Register 
           AIRCR = Application Interrupt/Reset Control Register 
           SCR = System Control Register 
           CCR = Configuration Control Register 
           SHPR = System Handlers Priority Register 
           SHCSR = System Handler Control and State Register 
           CFSR = Configurable Fault Status Registers 
           HFSR = Hard Fault Status Register 
           DFSR = Debug Fault Status Register 
           MMFAR = Mem Manage Address Register 
           BFAR = Bus Fault Address Register 
           AFSR = Auxiliary Fault Status Register 

       3)、系统时钟寄存器组 
           STM32的固件库中有如下定义: 
           typedef struct 
           { 
             vu32 CTRL; 
             vu32 LOAD; 
             vu32 VAL; 
             vuc32 CALIB; 
           } SysTick_TypeDef; 

           它们对应ARM手册中的名称为 
           CTRL = SysTick Control and Status Register 
           LOAD = SysTick Reload Value Register 
           VAL = SysTick Current Value Register 
           CALIB = SysTick Calibration Value Register 


    ================================= DMA ================================ 
    1、DMA普通模式和循环模式的区别 
       循环模式:用于处理一个环形的缓冲区,每轮传输结束时数据传输 的配置会自动地更新为初始状态,DMA传输会连续不断地进行。 
       普通模式:在DMA传输结束时,DMA通道被自动关闭,进一步的 DMA请求将不被满足。 

    2、DMA传输需要指定的条件: 
       传输源:DMA控制器从传输源读出数据; 
       传输目标:DMA控制器将数据传输的目标; 
       触发信号:用于触发一次数据传输的动作,执行一个单位的传输源至传输目标的数据传输。可以用来控制传输的启动条件。 



    ================================= ADC ================================ 
    1、STM32的内部温度传感器 
       STM32内部温度传感器与ADC的通道16相连,与ADC配 合使用实现温度测量。测量范围–40~125℃,精度 ± 1.5℃ 
       操作流程: 
       1)、设置ADC相关参数 
       // ADC1 configuration ----------------------------- 
       ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
       ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
       ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
       ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
       ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
       ADC_InitStructure.ADC_NbrOfChannel = 1; 
       ADC_Init(ADC1, &ADC_InitStructure); 

       2)、选中ADC1的通道16作为输入,设置采样时间17.1us ( Ncycle × tADC = 17.1靤 )。 
       // ADC1 regular channel16 Temp Sensor configuration 
       ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_55Cycles5); 

       3)、设置寄存器ADC_CR2中的TSVREFE位激活温度传感器 
       // Enable the temperature sensor and vref internal channel 
       ADC_TempSensorVrefintCmd(ENABLE); 
       
       4)、转换采样值为温度 
       ADC转换结束以后,读取ADC_DR寄存器中的结果,转换温度值计算公式如下: 
               V25 - VSENSE 
       T(℃) = ------------  + 25 
                Avg_Slope 
          V25:  温度传感器在25℃时 的输出电压,典型值1.43 V。 
         VSENSE:温度传感器的当前输出电压,与ADC_DR 寄存器中的结果ADC_ConvertedValue之间的转换关系为:  
                           ADC_ConvertedValue * Vdd 
                 VSENSE = -------------------------- 
                           Vdd_convert_value(0xFFF) 
         Avg_Slope:温度传感器输出电压和温度的关联参数,典型值4.3 mV/℃。 

         //Converted Temperature 
         Vtemp_sensor = ADC_ConvertedValue * Vdd / Vdd_convert_value; 
         Current_Temp = (V25 - Vtemp_sensor)/Avg_Slope + 25; 

    2、VDDA的电压范围 
        STM32的数据手册规定,VDD与VDDA之间的压差不能大于300mV。ADC的工作电压范围在2.4V~3.6V,供电电压VDD范围在2.0V~3.6V. 


    ================================= DAC ================================ 


    ============================= Advanced Timer ========================= 


    ============================== General Timer ========================= 


    ================================ Base Timer ========================== 


    ============================= Real-Time Clock ======================== 


    =========================== Independent watchdog ===================== 


    ============================= Windows Watchdog ======================= 


    ================================== FSMC ============================== 


    ================================== SDIO ============================== 


    ================================== USB =============================== 
    1、STM32的USB中断说明  
       STM32的USB模块可产生三种中断:USB唤醒中断、USB高优先级中断和USB低优先级中断,这三种中断对应事件如下: 
       1)、USB唤醒中断 - 在中断向量表中的位置是42 
       这个中断在USB设备从暂停模式唤醒时产生,唤醒事件由USB_ISTR寄存器的WKUP位标识。 

       2)、USB高优先级中断 - 在中断向量表中的位置是19 
       这个中断仅由USB同步(Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,正确传输事件由USB_ISTR寄存器的CTR位标识。 

       3)、USB低优先级中断 - 在中断向量表中的位置是20 
       这个中断由所有其它的USB事件产生,例如正确传输(不包括同步模式和双缓冲块模式)、USB复位等,事件标志位在USB_ISTR寄存器中。 

       在STM提供的STM32 USB 开发包中的例程包含了上述三种中断的处理方法。例如在USB Speaker例程中,CTR_HP函数处理USB高优先级中断;在所有例子中都有USB_Istr()函数处理USB低优先级中断。 



    ================================= bxCAN ============================== 
    1、CAN波特率的设定计数 
        
    ================================ Etherne ============================== 


    ================================== SPI =============================== 
    1、SPI外设的NSS引脚设置为通用IO口 
       由于SPI外设的SPI_CR1寄存器中SSM置1时,NSS引脚可被被释放用于GPIO使用,因此无论是在SPI的主模式或是从模式下均可以将NSS引脚释放,由软件或硬件进行NSS管理; 
       操作流程: 
       1)、初始化SPI外设,设置NSS由软件管理: 
       SPI_InitStructure.SPI_NSS= SPI_NSS_Soft; 
       2)、如果NSS引脚用于其他外设时,需要使能NSS输出: 
       SPI_SSOutputCmd(SPIx, ENABLE); 

    2、SPI 单线传输 
       此模式下限制:只能用作输入或者输出,或者工作在半双工模式下。 



    ================================== I2C =============================== 


    ================================= USART ============================== 


    ============================ Device Signature ======================== 
    1、    STM32F10xxx系列MCU内部含有一个出厂被固化的96bit唯一识别ID,该ID可以用于芯片加密、设备识别等一类特殊应用。 
    读取该ID的方法: 
        u32 DevID[3]; 
        DevID[0] = *(vu32*)(0x1ffff7e8); 
        DevID[1] = *(vu32*)(0x1ffff7ec); 
        DevID[2] = *(vu32*)(0x1ffff7f0); 

        数组DevID[3]中即保存了MCU的ID。 

    注:256K Flash或以上容量的STM32,仅“Z”版本才有,之前的“A”版本没有。 


    2、 


    ================================== I2C =============================== 



    ================================= Flash ============================== 
    1、STM32对内部Flash的保护措施  
       所有STM32的芯片都提供对Flash的保护,防止对Flash的非法访问 - 写保护和读保护。 
       1)、读保护即大家通常说的“加密”,是作用于整个Flash存储区域。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出: 
      通过调试器(JTAG或SWD); 
      从RAM中启动并执行的程序; 
       2)、写保护是以四页(1KB/页) Flash存储区为单位提供写保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志。   
       读与写设置的效果见下表: 
       读保护  写保护       对Flash的操作功能 
        有效   有效   CPU只能读,禁止调试和非法访问。 
        有效   无效   CPU可以读写,禁止调试和非法访问,页0~3为写保护。 
        无效   有效   CPU可读,允许调试和非法访问。 
        无效   无效   CPU可以读写,允许调试和非法访问。 

    2、当Flash读保护生效时,CPU执行程序可以读受保护的Flash区,但存在两个例外情况: 
       1)、调试执行程序时; 
       2)、从RAM启动并执行程序时 

       STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。 

    3、Flash保护相关函数 
       FLASH_Unlock();   //Flash解锁 
       FLASH_ReadOutProtection(DISABLE);  //Flash读保护禁止   
       FLASH_ReadOutProtection(ENABLE);   //Flash读保护允许 


    ================================== CRC =============================== 
    1、CRC计算公式 
       所有的STM32芯片都内置了一个硬件的CRC计算模块,可应用到通信程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式: 
        X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2 + X + 1 
       写成16进制就是:0x04C11DB7 

    2、使用这个内置CRC模块操作步骤: 
       复位CRC模块(设置CRC_CR=0x01),这个操作把CRC计算的余数初始化为0xFFFFFFFF 
       把要计算的数据按每32位分割为一组数据字,并逐个地把这组数据字写入CRC_DR寄存器(既下图中的绿色框) 
       写完所有的数据字后,就可以从CRC_DR寄存器(既下图中的兰色框)读出计算的结果。 

    注意:虽然读写操作都是针对CRC_DR寄存器,但实际上是访问的不同物理寄存器。 

    3、C语言描述的这个计算模块算法。可放在通信的另一端,对通信的正确性进行验证: 

       DWORD dwPolynomial = 0x04c11db7; 
       DWORD cal_crc(DWORD *ptr, int len) 
       { 
        DWORD xbit; 
        DWORD data; 
        DWORD CRC = 0xFFFFFFFF; // init 
        while (len--)  
        {    
          xbit = 1 << 31; 

          data = *ptr++; 
          for (int bits = 0; bits < 32; bits++)  
          { 
            if (CRC & 0x80000000)  
            { 
              CRC <<= 1; 
              CRC ^= dwPolynomial; 
            }else 
            CRC <<= 1; 
           if (data & xbit) 
           CRC ^= dwPolynomial; 

           xbit >>= 1; 
          } 
         } 
         return CRC; 
        } 

    注意: 
    1)、上述算法中变量CRC,在每次循环结束包含了计算的余数,它始终是向左移位(既从最低位向最高位移动),溢出的数据位被丢弃。 
    2)、输入的数据始终是以32位为单位,如果原始数据少于32位,需要在低位补0,当然也可以高位补0。 
    3)、假定输入的DWORD数组中每个分量是按小端存储。 
    4)、输入数据是按照最高位最先计算,最低位最后计算的顺序进行。 
    例如: 
    如果输入0x44434241,内存中按字节存放的顺序是:0x41, 0x42, 0x43, 0x44。计算的结果是:0xCF534AE1 
    如果输入0x41424344,内存中按字节存放的顺序是:0x44, 0x43, 0x42, 0x41。计算的结果是:0xABCF9A63 





    ====================================================================== 



                                 按照使用编译器 
    ====================================================================== 
    ================================== IAR =============================== 
    1、IAR环境下如果链接工程文件,出现堆栈溢出错误,该如何处理? 

       打开链接文件lnkarm_flash.xcl或者是lnkarm_ram.xcl  
    //*************************************************************************  
    // Stack and heap segments.  
    //*************************************************************************  

    -D_CSTACK_SIZE=400 <----------------------------------------修改这里  

    注:该修改方式仅适合IAR for ARM 4.xx版本。 

    2、IAR编译输出HEX格式的目标文件 
       1)、Options->C/C++ Compiler->Output->Generate debug information        选项前的钩去掉 
       2)、Options->Assembler->Output->Generate debug information             选项前的钩去掉 
       3)、Options->Linker->Output->Output File->Override default             选项前的钩选上并把文件名的后缀改成.hex 
       4)、Options->Linker->Output->Output File->Format->Other                选项前的钩选上并把Output格式改为intel-extended 
       经过以上设置,在Rebuld All之后会在/Debug/Exe下生成.hex格式目标文件  

    3、IAR编译输出BIN格式的目标文件 
       1)、Options->C/C++ Compiler->Output->Generate debug information        选项前的钩去掉 
       2)、Options->Assembler->Output->Generate debug information             选项前的钩去掉 
       3)、Options->Linker->Output->Output File->Override default             选项前的钩选上并把文件名的后缀改成.bin 
       4)、Options->Linker->Output->Output File->Format->Other                选项前的钩选上并把Output格式改为row-binary 
       经过以上设置,在Rebuld All之后会在/Debug/Exe下生成.bin格式目标文件  


    ================================== MDK =============================== 
    1、在MDK代码编辑环境下不能使用Goto Definition(用于查找某个变量的类型及定义)、Goto Reference(用于查找某个函数申明的原型)功能? 

    解决:打开Project->Target-Options->Output,将Browse Information复选框勾上。 


    2、当使用STM32固件库与RTX Kernel时,使用isr_evt_set(),事件无响应? 

    解决:编辑STM32固件库的“stm32f10x_vector.s”文件: 
    ... 
        IMPORT  SVC_Handler     ;name changed according to RTX usage 
        IMPORT  DebugMonitor 
        IMPORT  PendSV_Handler  ;修改加入 
        IMPORT  SysTick_Handler ;name changed according to RTX usage 
    ... 
        DCD  SVC_Handler 
        DCD  DebugMonitor 
        DCD  0                   ; Reserved 
        DCD  PendSV_Handler      ;修改加入 
        DCD  SysTick_Handler 

    ★emouse 思·睿博客文章★ 原创文章转载请注明:http://emouse.cnblogs.com
  • 相关阅读:
    Remove Duplicates from Sorted List
    Reverse Linked List II
    Remove Duplicates from Sorted List II
    Partition List
    iterator指针指向的元素
    Debug Assertion Failed! (VS)
    创建触发器,动作发送邮件到邮箱
    创建独立的监控模板
    zabbix添加被监控主机,内置的监控项,查看监控数据
    Oracle的sql脚本--->>Mysql的sql脚本
  • 原文地址:https://www.cnblogs.com/emouse/p/2198189.html
Copyright © 2011-2022 走看看