CAN编码

Posted 旭日初扬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAN编码相关的知识,希望对你有一定的参考价值。

#include "public.h"

//  CAN初始化
//  tsjw:重新同步跳跃时间单元,范围:CAN_SJW_1tq~ CAN_SJW_4tq
//  tbs2:时间段2的时间单元,范围:CAN_BS2_1tq~CAN_BS2_8tq;
//  tbs1:时间段1的时间单元,范围:CAN_BS1_1tq ~CAN_BS1_16tq
//  brp波特率分屏器:范围:1~1024            tq = (brp)* tpclk1
//波特率=Fpclk1/((tbs1+tbs2+1)*brp);
//mode:CAN_Mode_Normal 普通模式, CAN_Mode_LoopBack 回环模式  
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);
// 波特率 36M/((8+9+1)*4)=500kbps
void CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
  GPIO_InitTypeDef GPIO_InitStructure;    //  GPIO引脚
  CAN_InitTypeDef  CAN_InitStructure;     //  CAN
  CAN_FilterInitTypeDef CAN_FilterInitStructure;

  #if CAN_RX0_INT_ENABLE     //  不使用中断
      NVIC_InitTypeDef  NVIC_InitStructure;
  #endif

    //  CAN端口与时钟设置
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);   //  开启CAN1时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //  开启GPIOA时钟

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  // PA11  CAN1_RX
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; // 上拉输入模式
  GPIO_Init(GPIOA,&GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  // PA12  CAN1_TX
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; // 上拉输入模式
  GPIO_Init(GPIOA,&GPIO_InitStructure);

    //  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=mode;      //    模式设置
    CAN_InitStructure.CAN_SJW=tsjw;       //    重新同步跳跃宽度(tsjw)为tsjw+1个时间单位  CAN_SJW_1tq ~ CAN_SJW_4tq
    CAN_InitStructure.CAN_BS1 = tbs1;     //  Tbs1范围CAN_BS1_1tq ~ CAN_BS2_16tq
    CAN_InitStructure.CAN_BS2 = tbs2;     //  tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
    CAN_InitStructure.CAN_Prescaler=brp;  //  分频系数(Fdiv)为brp+1
    CAN_Init(CAN1,&CAN_InitStructure);    //  CAN1初始化

    // 过滤器配置
    CAN_FilterInitStructure.CAN_FilterNumber=0;                            //   FIFO0 过滤器0
      CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
      CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;      //
      CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;                    //  用于存储要筛选的ID,若筛选器工作在32位模式,它存储的是所选筛选器的高16位,若工作在16位模式它存储的就是一个完整的要筛选的ID
      CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;                //  用于存储要筛选的ID或掩码,工作在标识符列表模式,它的功能同CAN_FilterIdHigh  工作在掩码模式它存储的是CAN_FilterIdHigh成员对应的掩码,与CAN_FilterIdLow组成一组筛选器。
      CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
       CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;  //   关联过滤器 FIFO0
      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;      //   主优先级    抢占式优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;             //    副优先级响应式优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
#endif
}


#if CAN_RX0_INT_ENABLE   // 使能RX0中断

//  中断服务函数
void USB_LP_CAN_RX0_IRAHandler(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

u8 CAN_Send_Msg(u8 *msg,u8 len)
{
u8 CanTxmbox;
u16 i=0;
CanTxMsg TxMessage;
TxMessage.StdId=0x12;   //  用于存放报文的11位标准标识符,范围是0~0x7FF
TxMessage.ExtId=0x12;   //  用于存储报文的29位扩展标识符,范围是0-0x1FFFFFFF 与StdId这两个成员哪个有效要根据下面的IDE位配置

/* IDE=0  选择为标准标识符    
   IDE=1  选择为扩展标识符  
   用于存放扩展标志IDE位的值,其值可配置位CAN_ID_STD(标准帧报文)和CAN_ID_EXT(扩展帧报文)*/
TxMessage.IDE=0;     

/*RTR  =0  选择为数据帧      
  RTR = 1  选择为遥控帧
  用于存放报文类型标志的RTR位的值,当他的值为CAN_RTR_Data时表示本报文是数据帧,值为CAN_RTR_Remote时表示本报文是遥控帧。遥控帧(远程帧)没有数据位,所以当报文是遥控帧时,下面的Data[8]成员的内容是无效的*/
TxMessage.RTR = 0;     

/*设置数据帧的控制段
  DLC的大小为发送数据的长度,len最多为8 因为一个报文含0~8个字节数据
  用于存储数据帧数据段的长度,范围0-8  当报文是遥控帧时     DLC值为0
*/
TxMessage.DLC=len;      //  
                        //  Data[8]  用于存储数据帧中数据段的数据
                        
for(i=0;i<len;i++)             //  设置数据帧的控制段
    TxMessage.Data[i]=msg[i];    //  给数据帧数据赋值
CanTxmbox = CAN_Transmit(CAN1,&TxMessage);
i=0;
// 检测数据的发送状态。如果失败,等到i加到0xFFF退出循环,并返回"1";成功则返回"0".
while((CAN_TransmitStatus(CAN1,CanTxmbox)==CAN_TxStatus_Failed)&&(i<0xFFF))i++;
if(i>=0xFFF)return 1;
return 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<RxMessage.DLC;i++)
    buf[i]=RxMessage.Data[i];  
    return RxMessage.DLC;    
}
/*

库函数中提供了很多获取 CAN 状态标志的函数
CAN_TransmitStatus() 函数,
uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox)
@brief检查消息的传输。
* @param CANx:其中x可以是1或2来选择
* 外围。
* @param TransmitMailbox:所使用的邮箱号
* 传播。
* @retval CAN_TxStatus_Ok,如果CAN驱动发送消息,CAN_TxStatus_Failed
在另一种情况下。

CAN_MessagePending()函数,
uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber)
* @brief返回挂起消息的数量。
* @param CANx:其中x可以是1或2来选择can外围设备。
* @param fifonnumber:接收FIFO号码,CAN_FIFO0或CAN_FIFO1。
* @retval NbMessage:等待消息的数量。


CAN_GetFlagStatus()函数

FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG)
@brief检查是否设置了指定的CAN标志。
* @param CANx:其中x可以是1或2来选择can外围设备。
* @param CAN_FLAG:指定要检查的标志。该参数可以是以下标志之一:
  *                  - CAN_FLAG_EWG
  *                  - CAN_FLAG_EPV
  *                  - CAN_FLAG_BOF
  *                  - CAN_FLAG_RQCP0
  *                  - CAN_FLAG_RQCP1
  *                  - CAN_FLAG_RQCP2
  *                  - CAN_FLAG_FMP1   
  *                  - CAN_FLAG_FF1       
  *                  - CAN_FLAG_FOV1   
  *                  - CAN_FLAG_FMP0   
  *                  - CAN_FLAG_FF0       
  *                  - CAN_FLAG_FOV0   
  *                  - CAN_FLAG_WKU
  *                  - CAN_FLAG_SLAK  
  *                  - CAN_FLAG_LEC    
   @retval The new state of CAN_FLAG (SET or RESET).
 


*/

以上是关于CAN编码的主要内容,如果未能解决你的问题,请参考以下文章

大小端存储 --CAN 报文信号编码规则 intel & motorola

python2(中文编码问题):UnicodeDecodeError: 'ascii' codec can't decode byte 0x?? in position 1

python编码问题:UnicodeDecodeError: 'gbk' codec can't decode

python 编码问题:'ascii' codec can't encode characters in position 的解决方案

Python3文本编码错误:UnicodeDecodeError: 'gbk' codec can't decode byte

python编码问题——解决python3 UnicodeEncodeError: 'gbk' codec can't encode character 'xXX&#(