当前位置:文档之家› 基于STM32的CAN通讯,已在实际项目中应用

基于STM32的CAN通讯,已在实际项目中应用

与本程序代码相关部分的原理图及PCB,基于STM32F103VET6,已在项目中应用。

开头篇:STM32的CAN波特率计算STM32里的CAN 支持2.0A,2.0B, 带有FIFO,中断等, 这里主要提一下内部的时钟应用。

bxCAN挂接在APB1总线上,采用总线时钟,所以我们需要知道APB1的总线时钟是多少。

我们先看看下图,看看APB1总线时钟:APB1时钟取自AHB的分频, 而AHB又取自系统时钟的分频, 系统时钟可选HSI,HSE, PLLCLK, 这个在例程的RC设置里都有的,然后再看看有了APB1的时钟后,如何算CAN的总线速率, 先看下图:有了上边的这个图,基本就清楚了:总线时钟MHz (3+TS1+TS2)*(BRP+1)======================================================================下面是我的计算:CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;注意//#define CAN_BS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */ CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;CAN_InitStructure.CAN_Prescaler = 4;//2nominal bit time(3+5+1)tq=9tq关于分频系数,查看 system_stm32f10x.c下面的static void SetSysClockTo72(void) 函数:/* HCLK = SYSCLK *//* PCLK2 = HCLK *//* PCLK1 = HCLK/2 */所以can时钟 72MHZ/2/4=9 Mhz,tq=1/36Mhz波特率为 1/nominal bit time= 9/9=1MHZ=====================================================================void CAN_Configuration(void){CAN_InitTypeDef CAN_InitStructure;CAN_FilterInitTypeDef CAN_FilterInitStructure;/* CAN register init */CAN_DeInit();CAN_StructInit(&CAN_InitStructure);/* CAN cell init */CAN_InitStructure.CAN_TTCM=DISABLE;CAN_InitStructure.CAN_ABOM=DISABLE;CAN_InitStructure.CAN_AWUM=DISABLE;CAN_InitStructure.CAN_NART=DISABLE;CAN_InitStructure.CAN_RFLM=DISABLE;CAN_InitStructure.CAN_TXFP=DISABLE;CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;CAN_InitStructure.CAN_BS1=CAN_BS1_9tq;CAN_InitStructure.CAN_BS2=CAN_BS2_8tq;CAN_InitStructure.CAN_Prescaler=200;CAN_Init(&CAN_InitStructure);/* CAN filter init */CAN_FilterInitStructure.CAN_FilterNumber=0;CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;CAN_FilterInit(&CAN_FilterInitStructure);}注意//#define CAN_BS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */波特率10K,公式:72MHZ/2/200/(1+9+8)=0.01,即10Kbps正文篇:程序代码/* Includes ---------------------------------- --------------------------------*/#include "stm32f10x.h"#include "platform_config.h"#include "stm32f10x_rcc.h"#include "stm32f10x_flash.h"#include "stm32f10x_usart.h"#include "stm32f10x_gpio.h"#include "stm32f10x_tim.h"#include "stdio.h"ErrorStatus HSEStartUpStatus;void Uart1_PutChar(u8 ch);unsigned int j; //j=2-8/* Private typedef -----------------------------------------------------------*/ typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus; //状态量__IO uint32_t ret = 0; //用于中断返回的传递变量volatile TestStatus TestRx;CanTxMsg TxMessage;CanRxMsg RxMessage;unsigned char read_temp;unsigned char open_temp,stop_temp,top_temp;uint16_t CCR1_Val=0 ;#define start 50#define accelerate 10#define Period 999#define Prescaler 9//double percent=0.9;vu32 counter=0;vu32 compare ;uint16_t High_fre=900;unsigned int Tulun_i=0; //500次作为一个脉冲GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;//Private functions 函数---------------------------------------------------------*/void UART_Init(void);ErrorStatus HSEStartUpStatus;void RCC_Configuration(void); //申明时钟初始化函数void GPIO_Configuration(void); //申明IO初始化函数void NVIC_Configuration(void); //申明中断管理器初始化函数void CAN_Configuration(void); //申明CAN初始化函数void CAN_TX(unsigned char add,unsigned char data1,unsigned char data2);//申明CAN发送函数TestStatus CAN_RX(void); //申明带返回参数的CAN接收函数void LED_RESET(void);void PWM_startN(void);void PWM_start(void);/****** Main program ***********/int main(void){u32 n;/* 系统时钟初始化 */RCC_Configuration();/* 中断管理器初始化 */NVIC_Configuration();/* IO初始化*/GPIO_Configuration();UART_Init(); //初始化串口函数/* CAN初始化*/CAN_Configuration();TIM_TimeBaseStructure.TIM_Period = Period;TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);GPIO_ResetBits(GPIOA, GPIO_Pin_4);while (1){CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //开接收中断for(n=0;n<10000;n++); //延时if(ret == 1){for(j=0;j<8;j++) //发送8组数据到串口 {Uart1_PutChar(RxMessage.Data[j]);}open_temp=RxMessage.Data[0];top_temp=RxMessage.Data[1];stop_temp= RxMessage.Data[2];switch(open_temp){case 01:PWM_start(); break;case 02:PWM_startN();break;default: GPIO_ResetBits(GPIOA, GPIO_Pin_2);GPIO_ResetBits(GPIOA, GPIO_Pin_1); break;}ret = 0;}}}/* 开始输出PWM */void PWM_start(void){TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 1000-CCR1_Val;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC3Init(TIM2, &TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_Pulse = 1000-CCR1_Val;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC2Init(TIM2, &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);/* PWM1 Mode configuration: Channel2 */GPIO_ResetBits(GPIOA, GPIO_Pin_1);TIM_ARRPreloadConfig(TIM2, ENABLE);switch(top_temp){case 01: High_fre=100; break;case 02:High_fre=500 ;break;case 03:High_fre=900 ;break;default:break;}switch(stop_temp){case 01:compare=100000; break;case 02:compare=200000 ;break;case 03:compare=50000 ;break;default:break;}TIM_Cmd(TIM2, ENABLE);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/* TIM2 enable counter */}/* 停止输出PWM */void PWM_startN(void){TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1000-CCR1_Val;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC2Init(TIM2, &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC3Init(TIM2, &TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);/* PWM1 Mode configuration: Channel2 */GPIO_ResetBits(GPIOA, GPIO_Pin_2);TIM_ARRPreloadConfig(TIM2, ENABLE);switch(top_temp){case 01: High_fre=100; break;case 02:High_fre=500 ;break;case 03:High_fre=900 ;break;default:break;}switch(stop_temp){case 01:compare=100000; break;case 02:compare=200000 ;break;case 03:compare=50000 ;break;default:break;}TIM_Cmd(TIM2, ENABLE);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/* TIM2 enable counter */}void TIM2_IRQHandler(void){static unsigned int i=0;static unsigned int j=0;if (TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){if(counter<compare){if(i<(High_fre-start)/accelerate){TIM2->CCR2=1000-(start+i*accelerate);TIM2->CCR3=1000-(start+i*accelerate);Tulun_i++;counter++;if( Tulun_i==500){i++;Tulun_i=0;}}else{TIM2->CCR2=1000-High_fre;TIM2->CCR3=1000-High_fre;counter++;}}if(counter==compare){TIM2->CCR2=1000-(start+i*accelerate-j*accelerate);TIM2->CCR3=1000-(start+i*accelerate-j*accelerate);Tulun_i++;if( Tulun_i==500){j++;Tulun_i=0;}if(j==i){TIM2->CCR2=1000;TIM2->CCR3=1000;if(Tulun_i==0){TIM_Cmd(TIM2, DISABLE);TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE);i=0;j=0;counter=0;}}}TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}}/* 关LED */void LED_RESET(void){GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)0x00); //关LED GPIO_WriteBit(GPIOB, GPIO_Pin_1, (BitAction)0x00);}/*******************************************************************************Configures the different system clocks.*******************************************************************************/void RCC_Configuration(void){ErrorStatus HSEStartUpStatus;/* RCC system reset(for debug purpose) */RCC_DeInit(); //时钟控制寄存器全部恢复默认值/* Enable HSE */RCC_HSEConfig(RCC_HSE_ON); //外部高速时钟源开启(8M晶振)/* Wait till HSE is ready */HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部时钟就绪if(HSEStartUpStatus == SUCCESS) //如果时钟启动成功{/* HCLK = SYSCLK */RCC_HCLKConfig(RCC_SYSCLK_Div1); //定义AHB设备时钟为系统时钟1分频/* PCLK2 = HCLK */RCC_PCLK2Config(RCC_HCLK_Div1); //定义AHB2设备时钟为HCLK时钟1分频/* PCLK1 = HCLK/2 */RCC_PCLK1Config(RCC_HCLK_Div2); //定义AHB1设备时钟为HCLK时钟2分频/* Flash 2 wait state */FLASH_SetLatency(FLASH_Latency_2); //设定内部FLASH的的延时周期为2周期 /* Enable Prefetch Buffer */FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能FLASH预存取缓冲区/* PLLCLK = 8MHz * 9 = 72 MHz */RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //配置PLL时钟为外部高速时钟的9倍频/* Enable PLL */RCC_PLLCmd(ENABLE); //使能PLL时钟/* Wait till PLL is ready */while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟设置完成准备就绪 {}/* Select PLL as system clock source */RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //使用PLL时钟作为系统时钟源 /* Wait till PLL is used as system clock source *//* Wait till PLL is used as system clock source */while(RCC_GetSYSCLKSource() != 0x08) //返回系统所用时钟源确认为外部高速晶振,8M晶振。

相关主题