之前在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日

转载于:https://www.cnblogs.com/craigtao/p/3645148.html

STM32F103C8T6 CAN通信详解相关推荐

  1. OS--进程间通信详解(二)

    OS–进程间通信详解(二) 文章目录 OS--进程间通信详解(二) 一.进程间通信 1.互斥量 Futexes Pthreads中的互斥量 2.管程 3.消息传递 消息传递系统的设计要点 用消息传递解 ...

  2. OS--进程间通信详解(一)

    OS–进程间通信详解(一) 文章目录 OS--进程间通信详解(一) 一.进程间通信 1.竞态条件 2.临界区 3.忙等互斥 屏蔽中断 锁变量 严格轮询法 Peterson 解法 TSL指令 4.睡眠与 ...

  3. Java串口通信详解(转)

    Java串口通信详解(转) 作者:denimcc 日期:2007-05-11 序言     说到开源,恐怕很少有人不挑大指称赞.学生通过开源代码学到了知识,程序员通过开源类库获得了别人的成功经验及能够 ...

  4. 【流媒体服务器Mediasoup】 NodeJs与C++信令通信详解及Linux下管道通信的详解(五)

    目录 前言 匿名管道进程间通信 进程间管道 的创建与图解 MediaSoup中的管道创建 MediaSoup Channel的创建 NodeJs和 C++ 管道通信的过程 MediaSoup 消息确认 ...

  5. 【STM32】标准库与HAL库对照学习教程八--串口通信详解

    [STM32]标准库与HAL库对照学习教程八--串口通信详解 一.前言 二.准备工作 三.通信的基本概念 1.通信方式 2.串行通信与并行通信 (1)串行通信 (2)并行通信 3.异步通信与同步通信 ...

  6. IIC通信协议(硬件实现IIC通信详解I)

    IIC通信协议 什么是IIC协议 协议层 起始信号和停止信号 数据的有效性 什么是IIC协议 I2C(Inter-Integrated Circuit)通讯协议是由 Phiilps 公司开发的两线式串 ...

  7. MATLAB与51单片机进行串口通信详解

    目录 一.51单片机与电脑进行串口通信 二.MATLAB串口通信函数 三.串口属性 四.示例Demo 4.1 MATLAB接收单片机发来的数据 4.2 MATLAB向单片机发送数据控制LED 五.总结 ...

  8. S5PV210串口通信详解

    S5PV210串口通信详解 S5PV210概述: S5PV210有4路独立,异步,串行的输入输出IO口,UART支持的通信速率达到3Mbps. 一个周期数据的组成:1位起始位,8位有效数据位,1位奇偶 ...

  9. android传递socket对象,Android Socket通信详解

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时 ...

最新文章

  1. python使用fpdf将生成的长字符串手动换行写入pdf
  2. 根据数据库表gengxin实体类_Python学习第四十八天记录打call:SQLALchemy操作MySQL关系型数据库...
  3. 科大星云诗社动态20210424
  4. go map(映射)的概念、3种创建方式及map的CRUD操作
  5. Java泛型简介–第6部分
  6. Python NLP英文文本转小写
  7. JVM系列(之class文件)
  8. Python使用scrapy框架编写自动爬虫爬取京东商品信息并写入数据库
  9. Structs2-基础
  10. 盘点2017年最热门的10个增长黑客策略
  11. 用ipv6地址打开samba共享目录
  12. 个人作业——关于K米的产品案例分析
  13. 鉴相,鉴频以及环路跟踪算法的理解:
  14. 2048游戏DQN实验
  15. ResNet解析(二)
  16. 【年度榜单】2020大数据产业创新技术突破丨数据猿·金猿榜
  17. JavaScript:分支流程控制switch语句详解
  18. Windows Metro Style颜色色值表
  19. 使用 jodd:form tag
  20. 如何做好电脑重要文件数据的备份

热门文章

  1. python【蓝桥杯vip练习题库】ADV-172身份证排序
  2. python【蓝桥杯vip练习题库】ADV-188排列数
  3. sleep interrupted异常_Java高并发3中断线程以及isInterrupted与interrupted区别
  4. 边缘计算架构_多接入边缘计算框架与参考架构简介
  5. java instanceof 原理_java-在现代JVM实现中如何实现instanceof?
  6. 新建站点如何与服务器,新建站点如何收录更快
  7. 良品铺子如何通过网站推广打造国内休闲食品连锁零售企业?
  8. 企业网络推广期间对于易流失用户群体企业网络推广有话说
  9. 网站常规基本优化工作有哪些?
  10. java logout session_在jsp里做“退出登录”, session.setAttribute(id,null)居然出错。高手救命啊!...