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;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t Data[8];
} CanTxMsg;
这是定义一个can数据包的结构体,即一个CAN数据包包含以上几个部分。
现在我们思考一个问题:由于can可连接多个节点,如果一个系统为星形网络连接方式,那么主机应该怎样区别这些从机发送的信息呢?
答案在上面那个结构体中,我们可以给每个分机定义一个ID,那么主机在接收到分机发送的数据后,通过ID号判别接收到的信息是那个从机发送的。
注意: DLC定义发送数据的长度,其范围为:0~8。
下面我们来编写CAN驱动:
对CAN模块初始化
void CAN_CfgInit(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_PortInit();
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
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_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;
INT8U u8_IDE;
INT8U u8_RTR;
INT8U u8_DLC;
INT8U u8_FMI;
INT8U u8_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.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
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模块 使用详解
引用地址:
STM32 CAN模块使用详解
推荐阅读最新更新时间:2024-03-16 14:40
【STM32】STM32固件库(标准外设库)
标准外设库概述 STM32标准外设库是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。该函数库还包括每一个外设的驱动描述和应用实例,为开发者访问底层硬件提供了一个中间API,通过使用固件函数库,无需深入掌握底层硬件细节,开发者就可以轻松应用每一个外设。 因此,使用固态函数库可以大大减少开发者开发使用片内外设的时间,进而降低开发成本。每个外设驱动都由一组函数组成,这组函数覆盖了该外设所有功能。每个器件的开发都由一个通用的标准化的API去驱动。这里介绍的是V3.5版本的外设库,也是迄今最新的版本。 STM32F10x标准外设库文件结构 库的下载处是在ST公司的官方网站,下载链接:ST公司官方网站。
[单片机]
基于LPC2131嵌入式系统的CAN模块设计与实现
随着信息技术技术的飞速发展, ARM技术方案架构作为一种具备低功耗、高性能、以及小体积等特性的32位嵌入式微处理器,得到了众多的知识产权授权用户,其中包括世界顶级的半导体和系统公司。目前已被广泛的用于各类电子产品,汽车、消费娱乐、影像、工业控制、海量存储、网络、安保和无线等领域。被业界人士认为,基于ARM的技术方案是最具市场前景和市场优势的解决方案。 现场总线CAN是为解决现代汽车中众多的电控模块之间的数据交换而开发的一种串行通信协议。由于其具有多主站依据优先权进行总线访问,采用非破坏性总线仲裁,可完成对通信数据的错误检验和优先级判别,数据长度最多为8个字节,传输时间短,受干扰的概率低,抗干扰能力较强,通信速率最高可达1Mbit/s
[嵌入式]
stm32gpio的工作模式
1、推挽输出 可以输出高、低电平,连接数字器件;推挽结构一般是指两个三极管分别受两个互补 信号 的控制,总是在一个三极管导通的时候另一个截止。高低电平由 IC 的 电源 决定。 推挽电路是两个 参数 相同的三极管或 MOSFET ,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌 电流 ,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。 2、开漏输出 输出端相当于三极管的集电极,要得到高电平状态需要上拉 电阻 才行。适合于做电流型的驱动,其吸收电流的能力相对强(一般20mA以内)。 3、浮空输入 对于浮空输
[单片机]
stm32外部晶振由8m换成12m系统延时函数如何更改
下面我们就通过简单的三个步骤就可以让你随意的使用4—16MHz之内任何频点的晶振,我们以STM32F10x_StdPeriph_Lib_V3.4.0为例说明。 第一步,打开stm32f10x.h,将 #define HSE_VALUE ((uint32_t)8000000) 修改为: #define HSE_VALUE ((uint32_t)12000000) 第二步,打开system_stm32f10x.c,修改PLL参数,将 RCC- CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC- CFG
[单片机]
单片机学习之STM32中断
简介:STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。 1.中断优先级管理 嵌套向量中断控制器:Nested Vectored Interrupt Controller (NVIC) CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。 STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。 STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。 STM32F103系列上面,又只有60个可屏蔽中断(在
[单片机]
STM32 的看门狗
STM32 有两个看门 ,一个是独立看门狗,一个是窗口看门狗.这里先说独立看门狗. 独立看门狗的特性是,要利用片内的40k RC振荡器作为时钟据(说这个RC是相当的不准),优点就是,即使CPU主晶振 停了,即使CPU进入了休眠模式,狗也可以生效.当CPU进入休眠模式,并且是深度休眠的时候,这个看门狗可以作为一个CPU 的定时唤醒闹钟,以达到超低功耗的同时还会定时醒来.看门狗由于最大可以分频到256,看门狗定时器最大可以设置到0xfff,所以最最长的喂狗时间是26秒.....用于CPU的唤醒恰到好处。 用户手册: STM32F10xxx内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口
[单片机]
STM32的时钟系统学习笔记(基于STM32F407)
RCC(Reset clock Control 复位时钟控制器) 时钟源(时钟生成) 常规:外部晶振、芯片内部振荡器、锁相环(PLL) PS:(Phase Locked Loop): 为锁相回路或锁相环 其他:以太网、USB OTG FS、或其他外设的时钟源 STM32F407时钟树关系图(重点理解经常用到) 时钟总线 RCC通过多个预分频器配置时钟总线 PS:预分频器 (Prescaler-PSC)用来将定时器时钟源进行分频输出 总线类型:AHB、低速APB1、高速APB2 PS: AHB(Advanced High Performance Bus),高级高性能总线 APB(Advanc
[单片机]
STM32中将常量存储在FLASH中(CONST关键字)
今天在写程序时,想把一个字符串常量存储在STM32的FLASH中,看了一会儿别人的例子程序,知道是用const这个关键字,但第一次没有成功。 前提:我用的是STM32F103ZE单片机, FLASH的存储范围为:0x08000000~0x0807ffff, RAM的存储范围:0x20000000~0x200007ff 失败例子: #include..... 。。。。 int main(void) { u8 const c = somen ; while(1); } 通过调试,查看c 数组的存储位置为0x200*****的位置,常量仍旧处在RAM中。 成功的例子: #include..... u
[单片机]