基于STM32的CAN通讯,已在实际项目中应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
与本程序代码相关部分的原理图及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;//2
nominal 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晶振。
{
}
}
/* GPIO for CAN and GPIO for LEDs clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIO_CAN |
RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOC, ENABLE);
//使能由APB2时钟控制的外设中的PA,PB,PC和复用IO端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
/* CAN1 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能由APB1时钟控制的外设中的CAN1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能由APB1时钟控制的外设中的TIM2
}
/*******************************************************************************
UART_Init
*******************************************************************************/
void UART_Init(void)
{
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能串口1时钟
//******************************************************************************
// 串口1参数初始化定义部分,串口1参数为38400 , 8 ,1 ,N 接收中断方式
//******************************************************************************
USART_ART_BaudRate = 38400; //设定传输速率
USART_ART_WordLength = USART_WordLength_8b; //设定传输数据位数
USART_ART_StopBits = USART_StopBits_1; //设定停止位个数
USART_ART_Parity = USART_Parity_No ; //不用校验位
USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;
//不用流量控制
USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx; //使用接收和发送功能 USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能串口1接收中断
USART_Cmd(USART1, ENABLE); //使能串口1
// NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel; //使能串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//******************************************************************************
// 串口1所使用管脚输出输入定义
//******************************************************************************
// 定义UART1 TX (PA.09)脚为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //IO口的第九脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //IO口复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化串口1输出IO口
// 定义 USART1 Rx (PA.10)为悬空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //IO口的第十脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//IO口悬空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化串口1输入IO口
}
/** 串口发送一个字符 **/
void Uart1_PutChar(u8 ch) //串口1发送数据函数u8 ch 要发送的数据
{
USART_SendData(USART1, ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//等待数据发送完毕
}
/***** 配置GPIO口 *****/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*配置按键*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //端口模式为上拉输入方式 GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*配置CAN端口*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //IO端口的第8位
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //端口模式为上拉输入方式 GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //IO端口的第9位
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //端口模式为复用推拉输出方式 GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_CAN , ENABLE); //重定义CAN到PB口
/*配置TIM2_CH3*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*******************************************************************************
Description : Configures the nested vectored interrupt controller.
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //向量表位于FLASH
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 抢占式优先级2位,响应式优先级2位 /* Enable CAN1 RX0 interrupt IRQ channel */
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //选择CAN1的接收中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //中断优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中断子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能定义的CAN1中断 NVIC_Init(&NVIC_InitStructure); //用以上参数初始化中断管理器
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/******************************************************************************* Configures the CAN controller.
*******************************************************************************/
void CAN_Configuration(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN register init */
CAN_DeInit(CAN1); //复位CAN1的所有寄存器
CAN_StructInit(&CAN_InitStructure); //将寄存器全部设置成默认值
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE; //禁止时间触发通信方式
CAN_InitStructure.CAN_ABOM=DISABLE; //禁止CAN总线自动关闭管理
CAN_InitStructure.CAN_AWUM=DISABLE; //禁止自动唤醒模式
CAN_InitStructure.CAN_NART=ENABLE; //禁止非自动重传模式
CAN_InitStructure.CAN_RFLM=DISABLE; //禁止接收FIFO锁定
CAN_InitStructure.CAN_TXFP=DISABLE; //禁止发送FIFO优先级
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //设置CAN工作方式为正常收发模式
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //设置重新同步跳转的时间量子
CAN_InitStructure.CAN_BS1=CAN_BS1_4tq; //设置字段1的时间量子数
CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; //设置字段2的时间量子数
CAN_InitStructure.CAN_Prescaler=36; //配置时间量子长度为1周期 125Kb/s的波特率 CAN_Init(CAN1, &CAN_InitStructure); //用以上参数初始化CAN1端口
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=0; //选择CAN过滤器0 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //初始化为标识/屏蔽模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //选择过滤器为32位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //过滤器标识号高16位
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; //过滤器标识号低16位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //根据模式选择过滤
器标识号或屏蔽号的高16位
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; //根据模式选择过滤器标识号或屏蔽号的低16位
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0; //将FIFO 0分配给过滤器0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
}
/*******************************************************************************
* Function Name : CAN_RX
* Description :
* Input :
* Output :
* Return : PASSED if the reception is well done, FAILED in other case
*******************************************************************************/
TestStatus CAN_RX(void)
{
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //使能CAN1报文FIFO 0挂起中断
ret = 0xFF;
while(ret == 0xFF); //等待接收标示量改变
CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE); //关中断
return (TestStatus)ret; //返回接收状态是否成功
}
/*******************************************************************************
* Function Name : CAN_TX
* Description :
* Input :
* Output :
* Return :
*******************************************************************************/
void CAN_TX(unsigned char add,unsigned char data1,unsigned char data2)
{
uint32_t i = 0;
unsigned char TransmitMailbox;
CAN_InitTypeDef CAN_InitStructure;
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE; //禁止时间触发通信方式
CAN_InitStructure.CAN_ABOM=DISABLE; //禁止CAN总线自动关闭管理
CAN_InitStructure.CAN_AWUM=DISABLE; //禁止自动唤醒模式
CAN_InitStructure.CAN_NART=ENABLE; //禁止非自动重传模式
CAN_InitStructure.CAN_RFLM=DISABLE; //禁止接收FIFO锁定
CAN_InitStructure.CAN_TXFP=DISABLE; //禁止发送FIFO优先级
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //设置CAN工作方式为正常收发模式
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //设置重新同步跳转的时间量子
CAN_InitStructure.CAN_BS1=CAN_BS1_4tq; //设置字段1的时间量子数
CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; //设置字段2的时间量子数
CAN_InitStructure.CAN_Prescaler=36; //配置时间量子长度为5周期波特率500K
CAN_Init(CAN1, &CAN_InitStructure); //用以上参数初始化CAN1端口
/* transmit 1 message */
TxMessage.StdId=0x00; //配置报文的标准标识符
//TxMessage.ExtId=add; //配置扩屏标识符
TxMessage.IDE=CAN_ID_STD; //报文使用标准标识符+扩屏标识符方式
TxMessage.RTR=CAN_RTR_DATA; //报文为数据帧
TxMessage.DLC=8; //报文发送数据长度为2字节
TxMessage.Data[0]=data1; //要发送的数据第0字节
TxMessage.Data[1]=data2; //要发送的数据第1字节
TxMessage.Data[2]=0x00; //要发送的数据第3字节
TxMessage.Data[3]=0x00; //要发送的数据第4字节
TxMessage.Data[4]=0x00; //要发送的数据第5字节
TxMessage.Data[5]=0x00;
TxMessage.Data[6]=0x01;
TxMessage.Data[7]=0x01;
/*以上为发送数据报表*/
TransmitMailbox=CAN_Transmit(CAN1,&TxMessage); //发送报文并返回发送信箱的地址
i = 0;
while((CAN_TransmitStatus(CAN1,TransmitMailbox)== CANTXOK) && (i != 0xFF))
//检查报文发送是否完成
{
i++;
}
i = 0;
while((CAN_MessagePending(CAN1,CAN_FIFO0) < 1) && (i != 0xFF))//返回被挂起的报文量是否为0 {
i++;
}
}
/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
This function handles USB Low Priority or CAN RX0 interrupts
/******************************************************************************/
void USB_LP_CAN1_RX0_IRQHandler(void) //CAN中断函数
{
// CanRxMsg RxMessage;
ret = 0;
RxMessage.StdId=0x00; //初始化接收数据池
RxMessage.IDE=CAN_ID_STD;
RxMessage.DLC=0; //
RxMessage.FMI=0; //
RxMessage.Data[0]=0x00; //
RxMessage.Data[1]=0x00; //
RxMessage.Data[2]=0x00;
RxMessage.Data[3]=0x00;
RxMessage.Data[4]=0x00;
RxMessage.Data[5]=0x00;
RxMessage.Data[6]=0x00;
RxMessage.Data[7]=0x00;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //从CAN1口缓冲器FIFO 0接收报文到 RxMessage if(RxMessage.StdId==0x00&& RxMessage.DLC==8)//校验报文全部是否正确
{
ret = 1; //正确则返回1
//GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)0x01); //如果正确点亮LED1
}
CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE); //关接收中断
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif。