STM32 500kbps CAN通信源码

作者: 小古 分类: 电子技术 发布时间: 2013-1-26 ė18180 次浏览 60 条评论

有时硬件问题真真害死人,这代码调试了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

|

发表评论:

电子邮件地址不会被公开。 必填项已用*标注

Ɣ回顶部
sitemap