STM32 500kbps CAN通信源码
有时硬件问题真真害死人,这代码调试了3天怎样弄都不行,回环模式测试成功,后来发现是vs230坏了,换了个开发板通信成功!
本程序基于3.5库编写,在ST官方开发板上调试通过,成功和51单片机通信。整个工程源码见附件,51源码稍后公开。
void CAN_Mode_Init(void):CAN初始化函数
u8 Can_Send_Msg(u8* msg,u8 len):向CAN总线写数据
u8 Can_Receive_Msg(u8 *buf):从CAN总线读数据
下面是can.h源码
#ifndef __CAN_H
#define __CAN_H
#include "stm32f10x.h"
//CAN接收RX0中断使能
#define CAN_RX0_INT_ENABLE 0 //0,不使能;1,使能.
void CAN_Mode_Init(void);//CAN初始化
u8 Can_Send_Msg(u8* msg,u8 len); //发送数据
u8 Can_Receive_Msg(u8 *buf); //接收数据
#endif
下面是can.c源码
void CAN_Mode_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; #if CAN_RX0_INT_ENABLE NVIC_InitTypeDef NVIC_InitStructure; #endif /* PB8,PB9口线设置为AFIO模式, 切换到CAN功能 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /* 使能GPIO时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* 配置CAN信号接收引脚: RX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /* GPIO配置为上拉输入模式 */ GPIO_Init(GPIOB, &GPIO_InitStructure); /* 配置CAN信号发送引脚: TX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /* 配置为复用推挽输出 */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* 设置GPIO最大速度 */ GPIO_Init(GPIOB, &GPIO_InitStructure); /* 原生的CAN引脚和USB引脚是相同的口线,安富莱开发板使用引脚的重映射功能将CAN引脚切换到PB8,PB9 */ GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE); /* 使能CAN1的重映射 */ /* 使能CAN外设时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); CAN_DeInit(CAN1); /* 复位CAN寄存器 */ CAN_StructInit(&CAN_InitStructure); /* 填充CAN参数结构体成员为缺省值 */ //CAN单元设置 CAN_InitStructure.CAN_TTCM = DISABLE; /* 禁止时间触发模式(不生成时间戳), T */ CAN_InitStructure.CAN_ABOM = DISABLE; /* 禁止自动总线关闭管理 */ CAN_InitStructure.CAN_AWUM = DISABLE; /* 禁止自动唤醒模式 */ CAN_InitStructure.CAN_NART = DISABLE; /* 禁止仲裁丢失或出错后的自动重传功能 */ CAN_InitStructure.CAN_RFLM = DISABLE; /* 禁止接收FIFO加锁模式 */ CAN_InitStructure.CAN_TXFP = DISABLE; /* 禁止传输FIFO优先级 */ CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; /* 设置CAN工作模式 */ //设置波特率 //CAN 波特率 = RCC_APB1Periph_CAN / Prescaler / (SJW + BS1 + BS2) //CAN 波特率 = 360000000/6/(1+6+5)=500kHz \ 360000000/12/(1+2+3)=500khz CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq CAN_InitStructure.CAN_BS1=CAN_BS1_2tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler=12; //分频系数(Fdiv)为brp+1 // CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 /* 设置CAN滤波器0 */ CAN_FilterInitStructure.CAN_FilterNumber = 0; /* 滤波器序号,0-13,共14个滤波器 */ CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; /* 滤波器模式,设置ID掩码模式 */ CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; /* 32位滤波 */ CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; /* 掩码后ID的高16bit */ CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; /* 掩码后ID的低16bit */ CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; /* ID掩码值高16bit */ CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; /* ID掩码值低16bit */ CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; /* 滤波器绑定FIFO 0 */ CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; /* 使能滤波器 */ CAN_FilterInit(&CAN_FilterInitStructure); #if CAN_RX0_INT_ENABLE CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif } #if CAN_RX0_INT_ENABLE //使能RX0中断 //中断服务函数 void USB_LP_CAN1_RX0_IRQHandler(void) { CanRxMsg RxMessage; int i=0; CAN_Receive(CAN1, 0, &RxMessage); for(i=0;i<8;i++) printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]); } #endif //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) //len:数据长度(最大为8) //msg:数据指针,最大为8个字节. //返回值:0,成功; // 其他,失败; u8 Can_Send_Msg(u8* msg,u8 len) { u8 mbox; u16 i=0; CanTxMsg TxMessage; TxMessage.StdId=0x12; // 标准标识符为0 TxMessage.ExtId=0x12; // 设置扩展标示符(29位) TxMessage.IDE=0; // 使用扩展标识符 TxMessage.RTR=0; // 消息类型为数据帧,一帧8位 TxMessage.DLC=len; // 发送两帧信息 for(i=0;i<8;i++) TxMessage.Data[i]=msg[i]; // 第一帧信息 mbox= CAN_Transmit(CAN1, &TxMessage); i=0; while((CAN_TransmitStatus(CAN1, 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(CAN1,CAN_FIFO0)==0) return 0; //没有接收到数据,直接退出 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据 for(i=0;i<8;i++) buf[i]=RxMessage.Data[i]; return RxMessage.DLC; }
本文出自 小古Blog,转载时请注明出处及相应链接。
本文永久链接: http://blog.chdz1.com/?post=176