STM32 CAN模块使用

来源:本站
导读:目前正在解读《STM32 CAN模块使用》的相关信息,《STM32 CAN模块使用》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《STM32 CAN模块使用》的详细说明。
简介:STM32 CAN模块使用详解.重点介绍以STM32F103E系列芯片为基础介绍CAN 总线的使用方法。CAN 总线在控制领域使用的非常广泛,如今大多数CPU芯片外围都扩展CAN接口。

1. 硬件基础

CAN总线工作需要两根数据线,RX和TX,即为输入总线和输出总线。一般CPU与外界通信需要接一个驱动芯片(这点很像UART接口),常用的CAN芯片主要有:SN65VHD230、PCA82C250T等,本系统使用SN65VHD230作为CAN接口芯片。而CPU提供的CAN接口为CAN_L和CAN_H。

2. 软件设计

在进行软件设计时,我们首先来看这样的一个结构体:

typedef struct

{

uint32_t StdId;/*!< Specifies the standard identifier.

This parameter can be a value between 0 to 0x7FF. */

uint32_t ExtId;/*!< Specifies the extended identifier.

This parameter can be a value between 0 to 0x1FFFFFFF. */

uint8_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.

This parameter can be a value of @ref CAN_identifier_type */

uint8_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.

This parameter can be a value of @ref CAN_remote_transmission_request */

uint8_t DLC; /*!< Specifies the length of the frame that will be transmitted.

This parameter can be a value between 0 to 8 */

uint8_t Data[8];/*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */

} CanTxMsg;

这是定义一个can数据包的结构体,即一个CAN数据包包含以上几个部分。

现在我们思考一个问题:由于can可连接多个节点,如果一个系统为星形网络连接方式,那么主机应该怎样区别这些从机发送的信息呢?

答案在上面那个结构体中,我们可以给每个分机定义一个ID,那么主机在接收到分机发送的数据后,通过ID号判别接收到的信息是那个从机发送的。

注意: DLC定义发送数据的长度,其范围为:0~8。

下面我们来编写CAN驱动:

对CAN模块初始化

void CAN_CfgInit(void)

{

CAN_InitTypeDef CAN_InitStructure;

CAN_FilterInitTypeDefCAN_FilterInitStructure;

CAN_PortInit();

CAN_DeInit(CAN1);

CAN_StructInit(&CAN_InitStructure);

/* CAN cell init */

CAN_InitStructure.CAN_TTCM=DISABLE;

CAN_InitStructure.CAN_ABOM=DISABLE;

CAN_InitStructure.CAN_AWUM=DISABLE;

CAN_InitStructure.CAN_NART=DISABLE;

CAN_InitStructure.CAN_RFLM=DISABLE;

CAN_InitStructure.CAN_TXFP=DISABLE;

CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;

CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;

CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;

CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;

CAN_InitStructure.CAN_Prescaler=5;

CAN_Init(CAN1, &CAN_InitStructure);

/* CAN filter init */

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=0;

CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;

CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;

CAN_FilterInit(&CAN_FilterInitStructure);

CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

}

这里为can 定义一个专门的结构体,便于数据处理:

typedef struct CAN_Socket CAN;

struct CAN_Socket {

INT32U u32_StdId;

INT32U u32_ExtId;

INT8Uu8_IDE;

INT8Uu8_RTR;

INT8Uu8_DLC;

INT8Uu8_FMI;

INT8Uu8_data[8];

};

数据打包,并且发送

void CAN_TxSocket( CAN *can_Socket )

{

INT8U i = 0;

CanTxMsg TxMessage;

CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // CAN FIFO0 message pending interrupt enable

// Transmit a message

TxMessage.StdId=can_Socket->u32_StdId;

TxMessage.ExtId=can_Socket->u32_ExtId;

TxMessage.IDE=can_Socket->u8_IDE;

TxMessage.RTR= can_Socket->u8_RTR;

TxMessage.DLC=can_Socket->u8_DLC;

for( i =0; i<TxMessage.DLC; i++){

TxMessage.Data = can_Socket->u8_data;

}

CAN_Transmit(CAN1, &TxMessage);

CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE); // Disable interrupt handling

}

接收函数放在中断程序中处理:

void USB_LP_CAN1_RX0_IRQHandler(void)

{

CanRxMsg RxMessage;

INT8U i = 0;

INT8U u8_RxLen = 0;

RxMessage.StdId = 0x00;

RxMessage.ExtId = 0x00;

RxMessage.IDE = 0;

RxMessage.RTR = 0;

RxMessage.DLC = 0;

RxMessage.FMI = 0;

for( i=0;i<8;i++){

RxMessage.Data=0x00;

}

CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

u8_RxLen = RxMessage.DLC;

if((RxMessage.ExtId==0x12) && (RxMessage.IDE==CAN_ID_EXT)){

for( i=0;i<u8_RxLen; i++){

CAN_ReceiveBuff = RxMessage.Data;

}

}

}

这里只介绍CAN使用方法和主要驱动程序,测试程序可自行设计。

本人的测试程序:

~INT8U SendBuff1[]="Hello";

INT8U SendBuff2[]="World";

INT8U SendBuff3[]="ADC= 255";

void main(void)

{

System_HardwareInit();

while (1)

{

CAN_Tx(SendBuff1);

Disp_CanReceveData();

CAN_Tx(SendBuff2);

Disp_CanReceveData();

CAN_Tx(SendBuff3);

Disp_CanReceveData();

}

}

接收数据,并在液晶上打印出来!

void Disp_CanReceveData( void )

{

INT8U u8_CanRecBuff[64];

if(CAN_ReceiveBuff[0] == 'H'){

sprintf(( char *)u8_CanRecBuff,"CAN receve buff1 is : %s",CAN_ReceiveBuff);

GCLDASC_PutChar16x16Str(10,30,u8_CanRecBuff, Red, Green, 1);

}

if(CAN_ReceiveBuff[0] == 'W'){

sprintf(( char *)u8_CanRecBuff,"CAN receve buff2 is : %s",CAN_ReceiveBuff);

GCLDASC_PutChar16x16Str(10,50,u8_CanRecBuff, Red, Green, 1);

}

if(CAN_ReceiveBuff[0] == 'A'){

sprintf(( char *)u8_CanRecBuff,"CAN receve buff3 is : %s",CAN_ReceiveBuff);

GCLDASC_PutChar16x16Str(10,70,u8_CanRecBuff, Red, Green, 1);

}

}

提醒:《STM32 CAN模块使用》最后刷新时间 2024-03-14 01:08:11,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《STM32 CAN模块使用》该内容的真实性请自行鉴别。