基于STM32的CAN通讯已在实际项目中应用.docx
- 文档编号:8314863
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:24
- 大小:238.31KB
基于STM32的CAN通讯已在实际项目中应用.docx
《基于STM32的CAN通讯已在实际项目中应用.docx》由会员分享,可在线阅读,更多相关《基于STM32的CAN通讯已在实际项目中应用.docx(24页珍藏版)》请在冰豆网上搜索。
基于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;
注意//#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时钟作为系统时钟源 /*Wai
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 STM32 CAN 通讯 实际 项目 应用