stm32之CAN(二)

下面这个例程是通过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; 
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值