下面这个例程是通过CAN接收中断来实现CAN的回环测试。当测试成功时,LED2点亮,并且通过串口打印。
如下代码:
main.c
#include "stm32f10x.h"
#include "led.h"
#include "usart1.h"
void USART1_Configuration(void);
void LED_GPIO_Configuration(void);
void CAN_Configuration(void);
void CAN_NVIC_Configuration(void);
void CAN_Test(void);
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
volatile TestStatus TestRx;
/* 在中断处理函数中返回 */
__IO uint32_t ret = 0;
int main(void)
{
USART1_Configuration();//初始化串口
LED_GPIO_Configuration();//初始化LED
CAN_NVIC_Configuration();
CAN_Configuration();//初始化CAN
printf( "\r\n CAN 中断测试初始化成功...... \r\n" );
CAN_Test();
printf( "\r\n CAN 中断测试成功...... \r\n" );
while(1);
}
/*CAN GPIO 和时钟配置 以及CAN的控制器和过滤器配置*/
void CAN_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);
/* CAN1 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Configure CAN pin: RX */ // PB8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure CAN pin: TX */ // PB9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*CAN控制器初始化结构体*/
/* CAN register init */
CAN_DeInit(CAN1);//can寄存器复位
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE; // 时间触发通信禁止
CAN_InitStructure.CAN_ABOM=DISABLE; // 离线退出是在中断置位清0后退出
CAN_InitStructure.CAN_AWUM=DISABLE; // 自动唤醒模式:清零sleep
CAN_InitStructure.CAN_NART=DISABLE; // 自动重新传送报文,直到发送成功
CAN_InitStructure.CAN_RFLM=DISABLE; // FIFO没有锁定,新报文覆盖旧报文
CAN_InitStructure.CAN_TXFP=DISABLE; // 发送报文优先级确定:标志符
CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; // 回环模式
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; // 1tq、BS1、BS2的值跟波特率有关
CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
CAN_InitStructure.CAN_Prescaler=1; // 分频系数为1
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
/*CAN过滤器初始化结构体*/
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=0; //初始化过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//标识符屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//使用1个32位过滤器
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //过滤器标识符为0x00000000
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //过滤器屏蔽标识符为0x00000000,即不屏蔽任何消息
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0; //过滤器FIFO0指向过滤器0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
}
/*CAN的中断控制器设置*/
void CAN_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable CAN1 RX0 interrupt IRQ channel */
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; /*!< USB Device Low Priority or CAN1 RX0 Interrupts */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 主优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
TestStatus CAN_Interrupt(void)
{
CanTxMsg TxMessage;//定义消息发送结构体
uint32_t i = 0;
/* CAN FIFO0 message pending interrupt enable */
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //中断使能
/* transmit 1 message */
TxMessage.StdId=0x00; // 标准标识符为0
TxMessage.ExtId=0x1234; // 设置扩展标示符(29位)
TxMessage.IDE=CAN_ID_EXT; // 使用扩展标识符
TxMessage.RTR=CAN_RTR_DATA; // 消息类型为数据帧,一帧8位
TxMessage.DLC=2; // 发送两帧信息
TxMessage.Data[0]=0xDE; // 第一帧信息
TxMessage.Data[1]=0xCA; // 第二帧信息
CAN_Transmit(CAN1, &TxMessage);
/* initialize the value that will be returned */
ret = 0xFF;
/* receive message with interrupt handling */
i=0;
while((ret == 0xFF) && (i < 0xFFF))
{
i++;
}
if (i == 0xFFF)
{
ret=0;
}
/* disable interrupt handling */
CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE);
return (TestStatus)ret;
}
void CAN_Test(void)
{
TestRx = CAN_Interrupt();
if (TestRx == FAILED)
{
LED2( OFF ); // LED2 OFF;
}
else
{
LED2( ON ); // LED2 ON;
}
}
stm32f10x_it.c
#include "stm32f10x.h"
extern __IO uint32_t ret;
void USB_LP_CAN1_RX0_IRQHandler(void)//中断处理函数
{
CanRxMsg RxMessage;
RxMessage.StdId=0x00;
RxMessage.ExtId=0x00;
RxMessage.IDE=0;
RxMessage.DLC=0;
RxMessage.FMI=0;
RxMessage.Data[0]=0x00;
RxMessage.Data[1]=0x00;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
if((RxMessage.ExtId==0x1234) &&
(RxMessage.IDE==CAN_ID_EXT)&&
(RxMessage.DLC==2) &&
((RxMessage.Data[1]|RxMessage.Data[0]<<8)==0xDECA))
{
ret = 1;
}
else
{
ret = 0;
}
}