STM32F103C8T6 CAN通信詳解


之前在stm32f107上面整過can,這次換了一個芯片,是STM32F103C8T6,48引腳封裝的,把之前的107的程序移植過來的時候

不好使,無奈得重新配置,這次清楚的stm32的時鍾和can的波特率學習了一遍,

先介紹板子硬件資源:

HSE時鍾:8MHz;

MCU : STM32F103C8T6

CAN:一路;(注意:沒有端口映射,使用PA11(can接收),PA12(can發送));

一、時鍾配置

首先看看系統初始化時的時鍾配置(使用的HSE時鍾,只講解從HSE時鍾源到CAN時鍾線路上的配置)

先看初始化代碼中部分:

 1 ; Reset handler
 2 Reset_Handler    PROC
 3                  EXPORT  Reset_Handler             [WEAK]
 4      IMPORT  __main
 5      IMPORT  SystemInit
 6                  LDR     R0, =SystemInit
 7                  BLX     R0
 8                  LDR     R0, =__main
 9                  BX      R0
10                  ENDP
View Code

清楚的看到,在進入main函數之前,系統顯示進入 SystemInit() 函數,進到這里看看;

 1 void SystemInit (void)
 2 {
 3   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
 4   /* Set HSION bit */
 5   RCC->CR |= (uint32_t)0x00000001;
 6 
 7   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
 8 #ifndef STM32F10X_CL
 9   RCC->CFGR &= (uint32_t)0xF8FF0000;
10 #else
11   RCC->CFGR &= (uint32_t)0xF0FF0000;
12 #endif /* STM32F10X_CL */   
13   
14   /* Reset HSEON, CSSON and PLLON bits */
15   RCC->CR &= (uint32_t)0xFEF6FFFF;
16 
17   /* Reset HSEBYP bit */
18   RCC->CR &= (uint32_t)0xFFFBFFFF;
19 
20   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
21   RCC->CFGR &= (uint32_t)0xFF80FFFF;
22 
23 #ifdef STM32F10X_CL
24   /* Reset PLL2ON and PLL3ON bits */
25   RCC->CR &= (uint32_t)0xEBFFFFFF;
26 
27   /* Disable all interrupts and clear pending bits  */
28   RCC->CIR = 0x00FF0000;
29 
30   /* Reset CFGR2 register */
31   RCC->CFGR2 = 0x00000000;
32 #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
33   /* Disable all interrupts and clear pending bits  */
34   RCC->CIR = 0x009F0000;
35 
36   /* Reset CFGR2 register */
37   RCC->CFGR2 = 0x00000000;      
38 #else
39   /* Disable all interrupts and clear pending bits  */
40   RCC->CIR = 0x009F0000;
41 #endif /* STM32F10X_CL */
42     
43 #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
44   #ifdef DATA_IN_ExtSRAM
45     SystemInit_ExtMemCtl(); 
46   #endif /* DATA_IN_ExtSRAM */
47 #endif 
48 
49   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
50   /* Configure the Flash Latency cycles and enable prefetch buffer */
51   SetSysClock();
52 
53 #ifdef VECT_TAB_SRAM
54   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
55 #else
56   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
57 #endif 
58 }
View Code

面前一系列的RCC寄存器的初始化,還有一些條件編譯選項,那些都是無關緊要的,對寄存器的初始化,

還有就是根據mcu的型號選擇不同的編譯; 到最后那里調用了 SetSysClock() 函數,

我們在進入到這個函數里看看,代碼:

 1 static void SetSysClock(void)
 2 {
 3 #ifdef SYSCLK_FREQ_HSE
 4   SetSysClockToHSE();
 5 #elif defined SYSCLK_FREQ_24MHz
 6   SetSysClockTo24();
 7 #elif defined SYSCLK_FREQ_36MHz
 8   SetSysClockTo36();
 9 #elif defined SYSCLK_FREQ_48MHz
10   SetSysClockTo48();
11 #elif defined SYSCLK_FREQ_56MHz
12   SetSysClockTo56();  
13 #elif defined SYSCLK_FREQ_72MHz
14   SetSysClockTo72();
15 #endif
16  
17  /* If none of the define above is enabled, the HSI is used as System clock
18     source (default after reset) */ 
19 }
View Code

又是一些條件編譯,沒事,因為之前之前宏定義的是 

#define SYSCLK_FREQ_72MHz  72000000

所以程序進入到 SetSysClockTo72 函數中,看看這個函數里面:

  1 /**
  2   * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 
  3   *         and PCLK1 prescalers. 
  4   * @note   This function should be used only after reset.
  5   * @param  None
  6   * @retval None
  7   */
  8 static void SetSysClockTo72(void)
  9 {
 10   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
 11   
 12   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
 13   /* Enable HSE */    
 14   RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 15  
 16   /* Wait till HSE is ready and if Time out is reached exit */
 17   do
 18   {
 19     HSEStatus = RCC->CR & RCC_CR_HSERDY;
 20     StartUpCounter++; //HSE_STARTUP_TIMEOUT重拾計數,系統便不適用PLL,而使用內部8MHz晶振
 21   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
 22 
 23   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
 24   {
 25     HSEStatus = (uint32_t)0x01;
 26   }
 27   else
 28   {
 29     HSEStatus = (uint32_t)0x00;
 30   }  
 31 
 32   if (HSEStatus == (uint32_t)0x01)
 33   {
 34     /* Enable Prefetch Buffer */
 35     FLASH->ACR |= FLASH_ACR_PRFTBE;
 36 
 37     /* Flash 2 wait state */
 38     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
 39     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
 40 
 41  
 42     /* HCLK = SYSCLK */
 43     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
 44       
 45     /* PCLK2 = HCLK */
 46     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
 47     
 48     /* PCLK1 = HCLK */
 49     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;               //APB1分頻系數:2   craigtao 2014-4-4
 50 
 51 #ifdef STM32F10X_CL
 52     /* Configure PLLs ------------------------------------------------------*/
 53     /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
 54     /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
 55         
 56     RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
 57                               RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
 58     RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
 59                              RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
 60   
 61     /* Enable PLL2 */
 62     RCC->CR |= RCC_CR_PLL2ON;
 63     /* Wait till PLL2 is ready */
 64     while((RCC->CR & RCC_CR_PLL2RDY) == 0)
 65     {
 66     }
 67     
 68    
 69     /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
 70     RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
 71     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
 72                             RCC_CFGR_PLLMULL9); 
 73 #else    
 74     /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
 75     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
 76                                         RCC_CFGR_PLLMULL));
 77     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);        //PLL倍頻系數:9   craigtao 2014-4-4
 78 #endif /* STM32F10X_CL */
 79 
 80     /* Enable PLL */
 81     RCC->CR |= RCC_CR_PLLON;
 82 
 83     /* Wait till PLL is ready */
 84     while((RCC->CR & RCC_CR_PLLRDY) == 0)
 85     {
 86     }
 87     
 88     /* Select PLL as system clock source */
 89     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
 90     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
 91 
 92     /* Wait till PLL is used as system clock source */
 93     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
 94     {
 95     }
 96   }
 97   else
 98   { /* If HSE fails to start-up, the application will have wrong clock 
 99          configuration. User can add here some code to deal with this error */
100   }
101     StartUpCounter = 0x11223344;
102     HSEStatus = 0x22334455;
103 }
View Code

又是一些條件編譯,不用在乎,結合mcu手冊,關鍵的兩行代碼:

/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;               //APB1分頻系數:2   craigtao 2014-4-4

RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);        //PLL倍頻系數:9   craigtao 2014-4-4

程序注釋寫得很明白,can使用的時鍾是AHB低速APB1上的時鍾,這里配置分頻系數是 2 ; 時鍾源是PLL提供

在往上一級時鍾就是PLL時鍾,PLL時鍾倍頻系數是 9 ;作為APB1的輸入時鍾源

HSE也就是外部接入的 8MHz 的晶振,作為PLL的輸入時鍾源,

總結一下時鍾的流向:

        HSE (8 MHz) -------> PLL倍頻 (9 倍 = 72 MHz) ---------> APB1分頻 (1/2 倍 = 36MHz) ------> can工作時鍾 = 36 MHz 

 

二、can波特率配置

上面已經講了,can工作的時鍾是 : 36 MHz,清楚了這個以后,結合mcu手冊,進行can波特率的設置,就從代碼的角度講解,看can波特率設置代碼段:

CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; 
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq; 
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
CAN_InitStructure.CAN_Prescaler=60;

專用詞匯名稱在這里就不多講解了,現在給出個公式: 8 (晶振) x 9 (PLL倍頻) / 2 (APB1分頻) / 60 / (1 + 3 + 2) = 0.1 = 100 (K)

得到can的通信波特率 100 K;

就套用這個公司,關鍵是得到can的時鍾源,也就是第一里講的內容,

(以上只是個人的理解,沒有很詳細的寫出來,希望大家多多批評)       

                                                                                                     craigtao    2014年4月4日

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM