基于stm32can通讯已在实际项目中应用.docx
《基于stm32can通讯已在实际项目中应用.docx》由会员分享,可在线阅读,更多相关《基于stm32can通讯已在实际项目中应用.docx(58页珍藏版)》请在冰点文库上搜索。
基于stm32can通讯已在实际项目中应用
与本程序代码相关部分的原理图及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;
注意//#defineCAN_BS1_3tq ((uint8_t)0x02)/*!
<3timequantum*/
CAN_InitStructure.CAN_BS2=CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler=4;//2
nominalbittime(3+5+1)tq=9tq
关于分频系数,查看system_stm32f10x.c下面的staticvoidSetSysClockTo72(void)函数:
/*HCLK=SYSCLK*/
/*PCLK2=HCLK*/
/*PCLK1=HCLK/2*/
所以can时钟72MHZ/2/4=9Mhz,tq=1/36Mhz
波特率为1/nominalbittime=9/9=1MHZ
=====================================================================
voidCAN_Configuration(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CANregisterinit*/
CAN_DeInit();
CAN_StructInit(&CAN_InitStructure);
/*CANcellinit*/
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);
/*CANfilterinit*/
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);
}
注意//#defineCAN_BS1_3tq ((uint8_t)0x02)/*!
<3timequantum*/
波特率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"
ErrorStatusHSEStartUpStatus;
voidUart1_PutChar(u8ch);
unsignedintj;//j=2-8
/*Privatetypedef-----------------------------------------------------------*/
typedefenum{FAILED=0,PASSED=!
FAILED}TestStatus;//状态量
__IOuint32_tret=0;//用于中断返回的传递变量
volatileTestStatusTestRx;
CanTxMsgTxMessage;
CanRxMsgRxMessage;
unsignedcharread_temp;
unsignedcharopen_temp,stop_temp,top_temp;
uint16_tCCR1_Val=0;
#definestart50
#defineaccelerate10
#definePeriod999
#definePrescaler9
//doublepercent=0.9;
vu32counter=0;
vu32compare;
uint16_tHigh_fre=900;
unsignedintTulun_i=0;//500次作为一个脉冲
GPIO_InitTypeDefGPIO_InitStructure;
NVIC_InitTypeDefNVIC_InitStructure;
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
TIM_OCInitTypeDefTIM_OCInitStructure;
//Privatefunctions函数---------------------------------------------------------*/
voidUART_Init(void);
ErrorStatusHSEStartUpStatus;
voidRCC_Configuration(void);//申明时钟初始化函数
voidGPIO_Configuration(void);//申明IO初始化函数
voidNVIC_Configuration(void);//申明中断管理器初始化函数
voidCAN_Configuration(void);//申明CAN初始化函数
voidCAN_TX(unsignedcharadd,unsignedchardata1,unsignedchardata2);//申明CAN发送函数
TestStatusCAN_RX(void);//申明带返回参数的CAN接收函数
voidLED_RESET(void);
voidPWM_startN(void);
voidPWM_start(void);
/******Mainprogram***********/
intmain(void)
{
u32n;
/*系统时钟初始化*/
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)
{
case01:
PWM_start();break;
case02:
PWM_startN();break;
default:
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
GPIO_ResetBits(GPIOA,GPIO_Pin_1);break;
}
ret=0;
}
}
}
/*开始输出PWM*/
voidPWM_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_OCMode=TIM_OCMode_PWM1;
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);
/*PWM1Modeconfiguration:
Channel2*/
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
TIM_ARRPreloadConfig(TIM2,ENABLE);
switch(top_temp)
{
case01:
High_fre=100;break;
case02:
High_fre=500;break;
case03:
High_fre=900;break;
default:
break;}
switch(stop_temp)
{
case01:
compare=100000;break;
case02:
compare=200000;break;
case03:
compare=50000;break;
default:
break;}
TIM_Cmd(TIM2,ENABLE);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
/*TIM2enablecounter*/
}
/*停止输出PWM*/
voidPWM_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_Pulse=1000-CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OC3Init(TIM2,&TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Disable);
/*PWM1Modeconfiguration:
Channel2*/
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
TIM_ARRPreloadConfig(TIM2,ENABLE);
switch(top_temp)
{
case01:
High_fre=100;break;
case02:
High_fre=500;break;
case03:
High_fre=900;break;
default:
break;}
switch(stop_temp)
{
case01:
compare=100000;break;
case02:
compare=200000;break;
case03:
compare=50000;break;
default:
break;}
TIM_Cmd(TIM2,ENABLE);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
/*TIM2enablecounter*/
}
voidTIM2_IRQHandler(void)
{
staticunsignedinti=0;
staticunsignedintj=0;
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!
=RESET)
{
if(counter{
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*/
voidLED_RESET(void)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_0,(BitAction)0x00);//关LED
GPIO_WriteBit(GPIOB,GPIO_Pin_1,(BitAction)0x00);
}
/*******************************************************************************
Configuresthedifferentsystemclocks.
*******************************************************************************/
voidRCC_Configuration(void)
{
ErrorStatusHSEStartUpStatus;
/*RCCsystemreset(fordebugpurpose)*/
RCC_DeInit();//时钟控制寄存器全部恢复默认值
/*EnableHSE*/
RCC_HSEConfig(RCC_HSE_ON);//外部高速时钟源开启(8M晶振)
/*WaittillHSEisready*/
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分频
/*Flash2waitstate*/
FLASH_SetLatency(FLASH_Latency_2);//设定内部FLASH的的延时周期为2周期
/*EnablePrefetchBuffer*/
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能FLASH预存取缓冲区
/*PLLCLK=8MHz*9=72MHz*/
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);//配置PLL时钟为外部高速时钟的9倍频
/*EnablePLL*/
RCC_PLLCmd(ENABLE);//使能PLL时钟
/*WaittillPLLisready*/
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)//等待PLL时钟设置完成准备就绪
{
}
/*SelectPLLassystemclocksource*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//使用PLL时钟作为系统时钟源
/*Waitt