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(