四、STM32F103C8T6使用CAN口

本文介绍了如何在STM32F103C8T6开发中,使用MDK5编译环境和J-Link下载器,构建BSP_CAN模块,实现CAN总线数据的发送和接收,以及配置CAN中断处理。主要涉及BSP_CAN.c和BSP_CAN.h文件的编写和集成到工程中。
摘要由CSDN通过智能技术生成

零、所需文件及环境:       

        1、第三章建立好的串口1当调试口程序   

        2、编译环境MDK5(KEIL5)   

        3、一个STM32F103C8T6硬件

        4、一个下载器j-link 或 st-link等

        5.代码编辑器 Notepad++   (可以不要 用记事本也能编译  都是习惯的问题)

        6.USB转TTL设备  用于连接电脑串口助手

        7.一个CAN分析仪  用来监测CAN总线数据  

壹、复制第三章串口1当调试口程序

1.1 第0章为工程模版 但是真正应用时  灯、定时器、调试口 不管啥程序这仨都会用到 所以以后会把第三章程序当做我自己的基础工程。

1.2 复制第三章程序并修改名字

1.2 进入USER/BSP文件夹下 复制LED文件夹改为BSP_CAN

1.3 进入USER/BSP/BSP_CAN文件夹,修改文件名

贰、编写BSP_CAN.c与BSP_CAN.h代码

2.1 打开BSP_CAN.h修改为

#ifndef __BSP_CAN_H
#define __BSP_CAN_H

#include "stm32f10x.h"


extern void BSP_CAN_Init(void);
extern	u8 Can_Send_Msg_TEXT(u8* msg,u8 len);

#endif 


2.2 打开BSP_DEBUG.c修改为

#include "BSP_CAN.h"
#include "BSP_DEBUG.h"


#define CANx                    CAN1
#define CANx_RX_PIN             GPIO_Pin_11
#define CANx_TX_PIN             GPIO_Pin_12
#define CANx_GPIO_PORT          GPIOA                    
#define CANx_RX_IRQn            USB_LP_CAN1_RX0_IRQn
#define CANx_RX_Priority        6                       
#define CANx_RX_IRQHandler      USB_LP_CAN1_RX0_IRQHandler
#define CANx_CLK                RCC_APB1Periph_CAN1
#define CANx_GPIO_CLK           RCC_APB2Periph_GPIOA

 
/* 功能:	GPIO配置
	 参数:	无
	 返回值:无
 */
void BSP_CAN_Init(void)
{
	
	GPIO_InitTypeDef 				GPIO_InitStructure; 
	CAN_InitTypeDef        	CAN_InitStructure;
	CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
	NVIC_InitTypeDef  			NVIC_InitStructure;


	RCC_APB2PeriphClockCmd(CANx_GPIO_CLK, ENABLE);//使能PORTA时钟	                   											 
	RCC_APB1PeriphClockCmd(CANx_CLK, ENABLE);//使能CAN1时钟	
	//CAN_TX
	GPIO_InitStructure.GPIO_Pin = CANx_TX_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
	GPIO_Init(CANx_GPIO_PORT, &GPIO_InitStructure);			//初始化IO
	//CAN_RX
	GPIO_InitStructure.GPIO_Pin = CANx_RX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_Init(CANx_GPIO_PORT, &GPIO_InitStructure);			//初始化IO

	//CAN单元设置
	CAN_InitStructure.CAN_TTCM=DISABLE;			//非时间触发通信模式  
	CAN_InitStructure.CAN_ABOM=DISABLE;			//软件自动离线管理	 
	CAN_InitStructure.CAN_AWUM=DISABLE;			//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN_InitStructure.CAN_NART=ENABLE;			//禁止报文自动传送 
	CAN_InitStructure.CAN_RFLM=DISABLE;		 	//报文不锁定,新的覆盖旧的  
	CAN_InitStructure.CAN_TXFP=DISABLE;			//优先级由报文标识符决定 
	CAN_InitStructure.CAN_Mode= CAN_Mode_Normal;	        //模式设置: mode:0,普通模式;1,回环模式; 
	
	/* 设置波特率:36MHz/9/(2+1+1)=1mbps */
//	CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
//	CAN_InitStructure.CAN_BS1 = CAN_BS1_13tq;//250Kbps
//	CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
//	CAN_InitStructure.CAN_Prescaler = 9; 

	CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
	CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;//500Kbps
	CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
	CAN_InitStructure.CAN_Prescaler = 12;
	
//	CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;	
//	CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;//1Mbps
//	CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
//	CAN_InitStructure.CAN_Prescaler = 6;	

	CAN_Init(CANx, &CAN_InitStructure);        	//初始化CAN1 

	CAN_FilterInitStructure.CAN_FilterNumber=0;	//过滤器0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	//屏蔽位模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 	//32位宽 
	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;	//32位ID
	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0

	CAN_FilterInit(&CAN_FilterInitStructure);			//滤波器初始化
	
	CAN_ITConfig(CANx,CAN_IT_FMP0,ENABLE);				//FIFO0消息挂号中断允许.		    

	NVIC_InitStructure.NVIC_IRQChannel = CANx_RX_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CANx_RX_Priority;     // 主优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}


//中断服务函数			    
void CANx_RX_IRQHandler(void)
{
  	CanRxMsg RxMessage;
    CAN_Receive(CANx, 0, &RxMessage);
	DEBUGx_Send_ascii(&RxMessage.Data[0],8);
}


//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 Can_Send_Msg_TEXT(u8* msg,u8 len)
{	
	u8 mbox;
	u16 i=0;
	CanTxMsg TxMessage;
	TxMessage.StdId=0x12;			// 标准标识符 
	TxMessage.ExtId=0x12;			// 设置扩展标示符 
	TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	TxMessage.DLC=len;				// 要发送的数据长度
	for(i=0;i<len;i++)
	TxMessage.Data[i]=msg[i];			          
	mbox= CAN_Transmit(CANx, &TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CANx, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}
//can口接收数据查询
//buf:数据缓存区;	 
//返回值:0,无数据被收到;
//		 其他,接收的数据长度;
u8 Can_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CANx,CAN_FIFO0)==0)return 0;		//没有接收到数据,直接退出 
    CAN_Receive(CANx, CAN_FIFO0, &RxMessage);//读取数据	
    for(i=0;i<8;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}




叁、打开工程,将BSP_CAN.c添加入工程并添加头文件路径

肆、修改main函数

#include "stm32f10x.h"

#include "BSP_LED.h"
#include "BSP_DELAY.h"
#include "BSP_TIMER.h"
#include "BSP_DEBUG.h"
#include "BSP_CAN.h"


uint8_t CAN_TEXT[8] = {1,2,3,4,5,6,7,8};
int main(void)
{
	BSP_LED_Init();
	BSP_DELAY_Init();
//	BSP_TIMER_Init();
	BSP_DEBUG_Init(115200);
	BSP_CAN_Init();

	while(1)
	{
			Can_Send_Msg_TEXT(&CAN_TEXT[0],8);
			printf("uart1 running...\r\n");
			BSP_DELAY_ms(500);		
	}
}


伍、编译

5.1 一个警告 还是上一章的警告 不用管  抛掉出错的数据 编译器认为你那个变量没使用

陆、下载运行

6.1 调试口每隔500ms打印信息

6.2 can分析仪输出测试数据 can发送正常   每家分析仪使用都不一样 按人家的使用教程来就好 需要注意的是波特率和代码里面保持相同

6.3 can分析仪发送一条帧id为0x00000000  的数据帧 标准帧  数据为 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07     串口助手收到八个相同的数据   CAN接收正常 因为我们写的can接收中断处理函数就是 将can口收到的数据原封不动从调试口送出去

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值