STM32F072B-DISCO 是我认为性价比最高的一款CPU的demo系统,以前一直在用PIC的CPU但最近几年ST异军突起,几次课题查找芯片无一例外都是ST,像USB,CAN,ZIGBEE等,ST都做的很出色,特别是芯片太便宜了,几乎都是几块人民币,STM32F072B-DISCO 提供了大量例题,我通过对例题的分析做出简单扼要的笔记,以加深自己的理解。

第一篇:中断系统

我认为理解和掌握中断系统是会使CPU的唯一标准。

int main(void)
{
 
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f0xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f0xx.c file
     */

所有例题开始都有这么一段注释,在进入main之前CPU已经完成了一系列初始化工作,startup_stm32f0xx.s在后面必须认真分析
    /* Initialize LEDs mounted on STM32F072B-DISCO board */
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED4);
  STM_EVAL_LEDInit(LED5);
  STM_EVAL_LEDInit(LED6);
 
  /* Configure PA0 in interrupt mode */
  EXTI0_1_Config();         // 外部中断 0 1 配置

配置中断子程序

static void EXTI0_1_Config(void)
{
  /* Enable GPIOA clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

/* Configure PA0 pin as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Enable SYSCFG clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
 
  /* Connect EXTI0 Line to PA0 pin */
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

/* Configure EXTI0 line */
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);

/* Enable and set EXTI0 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);   开中断并设定优先级
}

打开stm32f0xx_misc.c

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint32_t tmppriority = 0x00;
 
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPriority)); 
   
  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
  {
    /* Compute the Corresponding IRQ Priority --------------------------------*/   
    tmppriority = NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel >> 0x02];          The corresponding IPR number, M, is given by M = N DIV 4
    tmppriority &= (uint32_t)(~(((uint32_t)0xFF) << ((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8)));
    tmppriority |= (uint32_t)((((uint32_t)NVIC_InitStruct->NVIC_IRQChannelPriority << 6) & 0xFF) << ((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8));   
   
    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel >> 0x02] = tmppriority;   设定优先级    
    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[0] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);  开启中断
  }
  else
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[0] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
}

上面的NVIC_Init 看上去有点复杂通过查看

STM32F0xxx Cortex-M0 programming manual.pdf

的73页,大概明白了计算过程

Doc ID 022979 Rev 1 73/91
4.2.6 Interrupt priority register (IPR0-IPR7)
Address offset: 0x0300
Reset value: 0x0000 0000

Table 27. IPR bit assignments
Bits Name Function
[31:24] Priority, byte offset 3 Each priority field holds a priority value, 0-192. The lower the value,
the greater the priority of the corresponding interrupt. The processor
implements only bits[7:6] of each field, bits[5:0] read as zero and       //这里是说数值越低优先越高,因为只有4个优先级所以每字节只是7和6位有效。
ignore writes. This means writing 255 to a priority register saves
value 192 to the register.

The IPR registers provide an 8-bit priority field for each interrupt. These registers are only
word-accessible. Each register holds four priority fields, as shown in Figure 14.
Figure 14. IPR register mapping
See Interrupt set-enable register (ISER) on page 71 Accessing the Cortex-M0 NVIC
registers using CMSIS on page 70 for more information about the interrupt priority array, that
provides the software view of the interrupt priorities.
Find the IPR number and byte offset for interrupt N as follows:
● The corresponding IPR number, M, is given by M = N DIV 4
● The byte offset of the required Priority field in this register is N MOD 4, where:
– byte offset 0 refers to register bits[7:0]
– byte offset 1 refers to register bits[15:8]              //计算方法
– byte offset 2 refers to register bits[23:16]
– byte offset 3 refers to register bits[31:24].

打开startup_stm32f0xx.s  详细分析

PUBLIC  __vector_table

DATA
__vector_table
        DCD     sfe(CSTACK)
        DCD     Reset_Handler                  ; Reset Handler

DCD     NMI_Handler                    ; NMI Handler
        DCD     HardFault_Handler              ; Hard Fault Handler
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     SVC_Handler                    ; SVCall Handler
        DCD     0                              ; Reserved
        DCD     0                              ; Reserved
        DCD     PendSV_Handler                 ; PendSV Handler
        DCD     SysTick_Handler                ; SysTick Handler

; External Interrupts
        DCD     WWDG_IRQHandler                ; Window Watchdog
        DCD     PVD_VDDIO2_IRQHandler          ; PVD and VDDIO2 through EXTI Line detect
        DCD     RTC_IRQHandler                 ; RTC through EXTI Line
        DCD     FLASH_IRQHandler               ; FLASH
        DCD     RCC_CRS_IRQHandler             ; RCC and CRS
        DCD     EXTI0_1_IRQHandler             ; EXTI Line 0 and 1            //向量表中外部中断 0 1,标号EXTI0_1_IRQHandler            
        DCD     EXTI2_3_IRQHandler             ; EXTI Line 2 and 3
        DCD     EXTI4_15_IRQHandler            ; EXTI Line 4 to 15

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
        THUMB

PUBWEAK Reset_Handler
        SECTION .text:CODE:NOROOT:REORDER(2) //SECTION .text:CODE:REORDER(2) modify bu hxc 2014.11.9
Reset_Handler
        LDR     R0, =SystemInit
        BLX     R0
        LDR     R0, =__iar_program_start
        BX      R0
       
        PUBWEAK NMI_Handler
        SECTION .text:CODE:NOROOT:REORDER(1)
NMI_Handler
        B NMI_Handler
       
       
        PUBWEAK HardFault_Handler
        SECTION .text:CODE:NOROOT:REORDER(1)
HardFault_Handler
        B HardFault_Handler
      
       
        PUBWEAK SVC_Handler
        SECTION .text:CODE:NOROOT:REORDER(1)
SVC_Handler
        B SVC_Handler
      
       
        PUBWEAK PendSV_Handler
        SECTION .text:CODE:NOROOT:REORDER(1)
PendSV_Handler
        B PendSV_Handler
       
       
        PUBWEAK SysTick_Handler
        SECTION .text:CODE:NOROOT:REORDER(1)
SysTick_Handler
        B SysTick_Handler
       
       
        PUBWEAK WWDG_IRQHandler
        SECTION .text:CODE:NOROOT:REORDER(1)
WWDG_IRQHandler
        B WWDG_IRQHandler
       
               
        PUBWEAK PVD_VDDIO2_IRQHandler
        SECTION .text:CODE:NOROOT:REORDER(1)
PVD_VDDIO2_IRQHandler
        B PVD_VDDIO2_IRQHandler
       
               
        PUBWEAK RTC_IRQHandler
        SECTION .text:CODE:NOROOT:REORDER(1)
RTC_IRQHandler
        B RTC_IRQHandler
       
               
        PUBWEAK FLASH_IRQHandler
        SECTION .text:CODE:NOROOT:REORDER(1)
FLASH_IRQHandler
        B FLASH_IRQHandler
       
               
        PUBWEAK RCC_CRS_IRQHandler
        SECTION .text:CODE:NOROOT:REORDER(1)
RCC_CRS_IRQHandler
        B RCC_CRS_IRQHandler
       
               
        PUBWEAK EXTI0_1_IRQHandler
        SECTION .text:CODE:NOROOT:REORDER(1)
EXTI0_1_IRQHandler
        B EXTI0_1_IRQHandler           //外部中断 0 1 跳转地址

打开stm32f0xx_it.c

/******************************************************************************/
/*                 STM32F0xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f0xx.s).                                            */
/******************************************************************************/
/**
  * @brief  This function handles External line 0 to 1 interrupt request.
  * @param  None
  * @retval None
  */
void EXTI0_1_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)
  {
    /* Toggle LED4 */                                            //中断处理内容
    STM_EVAL_LEDToggle(LED4);

/* Clear the EXTI line 0 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line0);       //退出前清除中断标志,以便接收下次中断
  }
}

打开stm32f0xx.h

WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                                     */
  PVD_VDDIO2_IRQn             = 1,      /*!< PVD and VDDIO2 supply comparator through EXTI Line detect Interrupt */
  RTC_IRQn                    = 2,      /*!< RTC through EXTI Line Interrupt                               */
  FLASH_IRQn                  = 3,      /*!< FLASH Interrupt                                               */
  RCC_CRS_IRQn                = 4,      /*!< RCC and CRS Interrupts                                        */
  EXTI0_1_IRQn                = 5,      /*!< EXTI Line 0 and 1 Interrupts                                  */  在这IRQ号=5
  EXTI2_3_IRQn                = 6,      /*!< EXTI Line 2 and 3 Interrupts

05-11 20:11