STM32F103C8T6 CAN通信详解
2014-04-04 14:41
288 查看
之前在stm32f107上面整过can,这次换了一个芯片,是STM32F103C8T6,48引脚封装的,把之前的107的程序移植过来的时候
不好使,无奈得重新配置,这次清楚的stm32的时钟和can的波特率学习了一遍,
先介绍板子硬件资源:
HSE时钟:8MHz;
MCU : STM32F103C8T6
CAN:一路;(注意:没有端口映射,使用PA11(can接收),PA12(can发送));
一、时钟配置
首先看看系统初始化时的时钟配置(使用的HSE时钟,只讲解从HSE时钟源到CAN时钟线路上的配置)
先看初始化代码中部分:
View Code
又是一些条件编译,不用在乎,结合mcu手册,关键的两行代码:
程序注释写得很明白,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波特率设置代码段:
专用词汇名称在这里就不多讲解了,现在给出个公式: 8 (晶振) x 9 (PLL倍频) / 2 (APB1分频) / 60 / (1 + 3 + 2) = 0.1 = 100 (K)
得到can的通信波特率 100 K;
就套用这个公司,关键是得到can的时钟源,也就是第一里讲的内容,
(以上只是个人的理解,没有很详细的写出来,希望大家多多批评)
craigtao 2014年4月4日
不好使,无奈得重新配置,这次清楚的stm32的时钟和can的波特率学习了一遍,
先介绍板子硬件资源:
HSE时钟:8MHz;
MCU : STM32F103C8T6
CAN:一路;(注意:没有端口映射,使用PA11(can接收),PA12(can发送));
一、时钟配置
首先看看系统初始化时的时钟配置(使用的HSE时钟,只讲解从HSE时钟源到CAN时钟线路上的配置)
先看初始化代码中部分:
/** * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 * and PCLK1 prescalers. * @note This function should be used only after reset. * @param None * @retval None */ static void SetSysClockTo72(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reached exit */ do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; //HSE_STARTUP_TIMEOUT重拾计数,系统便不适用PLL,而使用内部8MHz晶振 } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSERDY) != RESET) { HSEStatus = (uint32_t)0x01; } else { HSEStatus = (uint32_t)0x00; } if (HSEStatus == (uint32_t)0x01) { /* Enable Prefetch Buffer */ FLASH->ACR |= FLASH_ACR_PRFTBE; /* Flash 2 wait state */ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; /* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; /* PCLK1 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; //APB1分频系数:2 craigtao 2014-4-4 #ifdef STM32F10X_CL /* Configure PLLs ------------------------------------------------------*/ /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); /* Enable PLL2 */ RCC->CR |= RCC_CR_PLL2ON; /* Wait till PLL2 is ready */ while((RCC->CR & RCC_CR_PLL2RDY) == 0) { } /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); #else /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); //PLL倍频系数:9 craigtao 2014-4-4 #endif /* STM32F10X_CL */ /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { } } else { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ } StartUpCounter = 0x11223344; HSEStatus = 0x22334455; }
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日
相关文章推荐
- [ASP.NET]强大的网页处理类NSoup
- WDS、WPS及WIFI2.4/5G相关
- TaskStackBuilder 不支持Android 3.0以下的设备
- NABC
- 11
- 基本数据类型可以直接返回
- windows下eclipse java开发能正常运行,移植到linux下,从Mysql中读取数据,出现中文乱码
- Open Source and SOA, ESB and Security
- 最受欢迎的棋牌游戏
- Referenced file contains errors (http://struts.apache.org/dtds/struts-2.1.7.dtd).
- 高德地图iOS SDK V2.2.0新版本(2014-03-18)
- 马哥Linux系列之零基础企业级Linux系统工程师网络高级就业班培训课程分享
- 您试图从目录中执行CGI、ISAPI 或其他可执行程序,但该目录不允许执行程序
- .net中反射技术的应用
- 动画 + 设置contentoffset,然后就 蛋疼了,
- 努力不一定有收获
- JQuery中serialize()、serializeArray()和param()方法
- Q27:二叉搜索树与双向链表
- 傅立叶变换
- linux core dump学习