STM32——CAN通信升级版本(队列方式)

#ifndef _TYPE_H_
#define _TYPE_H_

/* exact-width signed integer types */
typedef   signed           char int8_t;
typedef   signed short     int int16_t;
typedef   signed           int int32_t;
typedef   signed       __int64 int64_t;


/* exact-width unsigned integer types */
typedef unsigned           char uint8_t;
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;
typedef unsigned           int size_t;
typedef unsigned       __int64 uint64_t;

#ifndef NULL
#ifdef __cplusplus              // EC++
#define NULL   0
#else
#define NULL   ((void *) 0)
#endif
#endif

#ifndef boolean
typedef uint8_t boolean;
#endif

#ifndef TRUE
#define TRUE  1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#endif /* _TYPE_H_ */

#ifndef _CAN_QUEUE_H_
#define _CAN_QUEUE_H_

#include "stm32f10x_can.h"
#include "type.h"

#define CAN_TX_SIZE      0x25

typedef enum
{
  CAN_ERROR = 0,
  CAN_OK    = 1,
  CAN_BUSY  = 2,
} can_queue_status_t;

typedef CanTxMsg  can_frame_t;

typedef struct
{
  uint32_t write;
  uint32_t read;
  boolean is_full;
  uint32_t length;
  can_frame_t *frame;
} can_queue_t;

extern can_queue_t can_queue_send;

void CanQueueInit(void);
uint8_t CanQueueRead(can_queue_t *q, can_frame_t *frame);
uint8_t CanQueueWrite(can_queue_t *q, can_frame_t *frame);

#endif /* _CAN_QUEUE_H_ */
#include "can_queue.h"
#include <string.h>
#include "debug.h"

static can_frame_t tx[CAN_TX_SIZE] = {0};

can_queue_t can_queue_send =
{
  0,
  0,
  FALSE,
  CAN_TX_SIZE,
  tx
};

const can_frame_t frame_init =
{
  0,
  0,
  0,
  0,
  0,
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};

static void can_queue_init(can_queue_t *q, can_frame_t *frame, uint8_t length)
{
  uint8_t i;

  q->write = 0;
  q->read  = 0;
  q->is_full = FALSE;
  q->length = length;
  q->frame = frame;

  for(i = 0; i < length; ++i)
  {
    q->frame[i] = frame_init;
  }
}

static can_frame_t *can_frame_malloc(can_queue_t *q)
{
  can_frame_t *frame;

  if(NULL == q)
  {
    return NULL;
  }
  if(TRUE == q->is_full)
  {
    return NULL;
  }

  frame = &(q->frame[q->write++]);

  if(q->write >= q->length)
  {
    q->write = 0;
  }
  if(q->write == q->read)
  {
    q->is_full = TRUE;
  }

  *frame = frame_init;

  return frame;
}

static void can_frame_clear(can_frame_t *frame)
{
  can_frame_t *dst = frame;

  dst->StdId = 0;
  dst->DLC = 0;
  dst->IDE = CAN_Id_Standard;
  dst->RTR = CAN_RTR_Data;
  memset(dst->Data, 0, 8);
}

static void can_frame_copy(can_frame_t *dst, can_frame_t *src)
{
  can_frame_t *dst_tmp = dst, *src_tmp = src;

  dst_tmp->StdId = src_tmp->StdId;
  dst_tmp->DLC = src_tmp->DLC;
  dst_tmp->IDE = src_tmp->IDE;
  dst_tmp->RTR = src_tmp->RTR;
  memcpy(dst_tmp->Data, src_tmp->Data, 8);
}

uint8_t CanQueueRead(can_queue_t *q, can_frame_t *frame)
{
  uint8_t status = CAN_ERROR;

  if(NULL == q)
  {
    return CAN_ERROR;
  }

  if((q->read != q->write) || (q->is_full == TRUE))
  {
    can_frame_copy(frame, &q->frame[q->read]);
    can_frame_clear(&q->frame[q->read]);
    q->read += 1;

    if(q->read >= q->length)
    {
      q->read = 0;
    }
    q->is_full = FALSE;

	status = CAN_OK;
  }

  return status;
}

uint8_t CanQueueWrite(can_queue_t *q, can_frame_t *frame)
{
  can_frame_t *dst;

  dst = can_frame_malloc(q);

  if(NULL == dst)
  {
    return CAN_ERROR;
  }

  can_frame_copy(dst, frame);

  return CAN_OK;
}

void CanQueueInit(void)
{
  can_queue_init(&can_queue_send, tx, CAN_TX_SIZE);
}
#ifndef _CAN_H_
#define _CAN_H_

#include "can_queue.h"
#include "type.h"
#include "debug.h"

void CANInit(void);
void CanSendMsg(can_frame_t *frame);

#ifdef CONFIG_CAN
void can_general(void);
#endif

#endif /* _CAN_H_ */
#include "can.h"
#include "stm32f10x_can.h"
#include "stm32f10x.h"
#include "delay.h"
#include "target.h"
#include "string.h"

static void can_gpio_clk_init(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
  GPIO_PinRemapConfig(GPIO_Remap2_CAN1, ENABLE);
}

static void can_gpio_init(void)
{
  can_gpio_clk_init();

  CAN_TX_CONFIG();
  CAN_RX_CONFIG();
}

static void can_mode_init(void)
{
  CAN_InitTypeDef CAN_InitStructure;

  CAN_DeInit(CAN_CHANNEL);

  CAN_InitStructure.CAN_TTCM = DISABLE;
  CAN_InitStructure.CAN_ABOM = ENABLE ;
  CAN_InitStructure.CAN_AWUM = DISABLE;
  CAN_InitStructure.CAN_NART = ENABLE ;
  CAN_InitStructure.CAN_RFLM = DISABLE;
  CAN_InitStructure.CAN_TXFP = DISABLE;
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;  // baund = APB1/((tbs1+1+tbs2+1+1)*brp)  --- APB1 = 36K
  CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
  CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
  CAN_InitStructure.CAN_Prescaler = 8;
  CAN_Init(CAN_CHANNEL, &CAN_InitStructure);
}

static void can_nvic_init(void)
{
  NVIC_InitTypeDef  NVIC_InitStructure;

  CAN_ITConfig(CAN_CHANNEL, CAN_IT_FMP0, ENABLE);

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

static void can_filter_init(void)
{
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;

  CAN_FilterInitStructure.CAN_FilterNumber = 0;
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
}

void CANInit(void)
{
  can_gpio_init();
  can_mode_init();
  can_filter_init();
  can_nvic_init();
}

void CanSendMsg(can_frame_t *frame)
{
  int i;
  CAN_Transmit(CAN_CHANNEL, frame);
  for(i=0;i<1000;++i);
}

void CAN1_RX0_IRQHandler(void)
{
  CanRxMsg RxMessage;
  CanTxMsg TxMessage;
  int i = 0;
  CAN_Receive(CAN_CHANNEL, 0, &RxMessage);

#if 1
  TxMessage.StdId = 0x101;
  TxMessage.IDE = CAN_Id_Standard;
  TxMessage.RTR = CAN_RTR_Data;
  TxMessage.DLC = RxMessage.DLC;
  for(i = 0; i < TxMessage.DLC; i++)
  {
    TxMessage.Data[i] = RxMessage.Data[i];
  }
  CanQueueWrite(&can_queue_send, &TxMessage);
#endif
}

#ifdef CONFIG_CAN
void can_general(void)
{
  int i;
  can_frame_t frame;
  uint8_t buffer[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};

  frame.StdId = 0x11;
  frame.DLC = 6;
  frame.IDE = CAN_Id_Standard;
  frame.RTR = CAN_RTR_Data;
  memcpy(frame.Data, buffer, 6);

  //CanQueueWrite(&can_queue_send, &frame);
  for(i = 0; i < 7000; ++i);
}
#endif



  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32单片机CAN通信程序是一种用于实现CAN通信的程序,主要用于将STM32单片机与其他CAN设备进行数据传输。 首先,需要在STM32单片机上配置CAN总线控制器。可以通过寄存器设置来配置CAN通信参数,例如波特率、帧格式、滤波器设置等。配置完毕后,需要初始化CAN总线控制器,使其能够开始接收和发送CAN消息。 在程序中,需要设置中断处理函数来处理CAN接收中断和CAN发送中断。当CAN总线控制器接收到CAN消息时,会产生接收中断,可以在中断处理函数中读取接收到的CAN数据并进行相应的处理。当需要发送CAN消息时,可以调用相应的函数来发送数据。 在主程序中,需要进行CAN消息的发送和接收操作。可以通过调用相应的函数来发送CAN消息,函数的参数为CAN消息的标识符、数据长度和数据内容。同时,需要定期检查CAN总线控制器的状态,以确定是否有新的CAN消息到达。 为了更好地管理CAN消息,可以建立一个缓冲区来存储接收到的CAN消息。可以使用队列或环形缓冲区来管理CAN消息的接收和发送,从而实现异步的CAN通信。 总之,STM32单片机CAN通信程序的实现需要进行CAN总线控制器的配置和初始化,设置中断处理函数来处理接收和发送中断,以及在主程序中进行CAN消息的发送和接收操作。同时,可以建立一个缓冲区来存储接收到的CAN消息,从而实现可靠的CAN通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值