STM32--CAN简单接收和发送

发布者:平和的心情最新更新时间:2018-09-02 来源: eefocus关键字:STM32  CAN  接收和发送 手机看文章 扫描二维码
随时随地手机看文章

前面对CAN原理进行了讲解,这里我用一个简单的例子来说明CAN的使用。我使用的STM32芯片是STM32F103ZE,几个基本的配置是:

1.配置CAN时钟:

 /* CAN Periph clock enable */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);

2.CAN管脚配置,这里使用的PB11,PB12管脚:

/* Configure CAN pin: RX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
  
 /* Configure CAN pin: TX */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOA, &GPIO_InitStructure);  

3.中断配置,这里打开CAN的接收和发送中断:

/* CAN RX interrupt */
NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN_RX0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);     
    
 /* CAN TX interrupt */
 NVIC_InitStructure.NVIC_IRQChannel=USB_HP_CAN_TX_IRQChannel; 
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);   

这里需要注意的是CAN的发送中断,发送中断是发送邮箱中数据发送完毕后产生的发送完毕邮箱空中断--这和USART发送中断不同。详细点说CAN发送中断是指CAN的三个发送邮箱中的其中一个由满到发送数据完毕后空才产生的中断,当原来发送邮箱本来就是空的则不会产生发送中断。

4.CAN初始化配置:

void CAN_Ini(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
  /* CAN register init */
  CAN_DeInit();
  CAN_StructInit(&CAN_InitStructure);

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;  //禁止时间触发通信模式
  CAN_InitStructure.CAN_ABOM=DISABLE;  //软件对CAN_MCR寄存器的INRQ位进行置1随后清0后,一旦硬件检测
                                       //到128次11位连续的隐性位,就退出离线状态。
  CAN_InitStructure.CAN_AWUM=DISABLE;  //睡眠模式通过清除CAN_MCR寄存器的SLEEP位,由软件唤醒
  CAN_InitStructure.CAN_NART=DISABLE;   //CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)
  CAN_InitStructure.CAN_RFLM=DISABLE;  //在接收溢出时FIFO未被锁定,当接收FIFO的报文未被读出,下一个收到的报文会覆盖原有的报文
  CAN_InitStructure.CAN_TXFP=ENABLE;  //用来使能或者失能发送FIFO优先级,由发送的请求顺序决定
 CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//CAN硬件工作在正常模式

 switch(CAN_BPP)
 {
    //总体配置保持,tBS1>=tBS2,tBS2>=1个CAN时钟周期,tBS2>=2tSJW
  case 100000:
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;   //重新同步跳跃宽度
  CAN_InitStructure.CAN_BS1=CAN_BS1_10tq;  //设定时间段1的时间单位数目
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;   //设定时间段2的时间单位数目
  CAN_InitStructure.CAN_Prescaler=20;         //一个时间单位的长度//(pclk1/((4+8+8)*9)) = 36Mhz/18/20 = 100Kbits
  break;
  case 50000:
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1=CAN_BS1_10tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=40;    //(pclk1/((4+8+8)*9)) = 36Mhz/18/40 = 50Kbits
  break;

  case 20000:
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1=CAN_BS1_10tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=100;    //(pclk1/((4+8+8)*9)) = 36Mhz/18/100 = 20Kbits
  break;
  case 250000:
  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=9;    //(pclk1/((1+8+7)*9)) = 36Mhz/16/9 = 250Kbits
  break;

  case 500000:
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;    //重新同步跳跃宽度1个时间单位
  CAN_InitStructure.CAN_BS1=CAN_BS1_6tq;    //时间段1为6个时间单位
  CAN_InitStructure.CAN_BS2=CAN_BS2_5tq;    //时间段2为5个时间单位
  CAN_InitStructure.CAN_Prescaler=6;        //(pclk1/((1+6+5)*6)) = 36Mhz/12/6 = 500Kbits设定了一个时间单位的长度9
  break;
  default:
  break;

 }

  CAN_Init(&CAN_InitStructure);

  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=0;     //指定了待初始化的过滤器0
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;      //指定了过滤器将被初始化到的模式为标识符屏蔽位模式
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  //给出了过滤器位宽1个32位过滤器
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;                  //用来设定过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个)
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;                  //用来设定过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;              //用来设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;              //用来设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_IT_FMP0;  //设定了指向过滤器的FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;              //使能过滤器
  CAN_FilterInit(&CAN_FilterInitStructure);

  /* CAN FIFO0 message pending interrupt enable */ 
  CAN_ClearITPendingBit(CAN_IT_FF0);
  CAN_ClearITPendingBit(CAN_IT_FOV0);
  CAN_ClearITPendingBit(CAN_IT_FF1);
  CAN_ClearITPendingBit(CAN_IT_FOV1);
  CAN_ClearITPendingBit(CAN_IT_RQCP0);
  CAN_ClearITPendingBit(CAN_IT_RQCP1);
  CAN_ClearITPendingBit(CAN_IT_RQCP2);
  CAN_ITConfig(CAN_IT_FMP0, ENABLE);  //使能接收中断
    //CAN_ITConfig(CAN_IT_TME, ENABLE); //TransmitMailbox empty,发送中断在CAN_Transmit()后才能打开,用来判断发送完毕发送下一个数据

}

5.实现CAN的发送中断和接收中断,这里我们只用了一个发送邮箱进行发送--简单方便:

void USB_LP_CAN_RX0_IRQHandler(void)  //接收中断
{
  CanRxMsg RxMessage;
  U8 i=0;
  U8 targetid=0;

  //如果是标准帧
    CAN_Receive(CAN_FIFO0, &RxMessage);
    if(RxMessage.IDE==CAN_ID_STD)//只收标准帧数据
    {
        if((RxMessage.StdId&0x1F)==PCL_ID+bmqnum)   //接收到ID是取后5位是自己的ID
        {
            //每个完整的数据,以|开头,下面是ID
            while(!QIn(&Qlinecanrx,'|')){}
            targetid=(RxMessage.StdId>>6)&0x1F;
            while(!QIn(&Qlinecanrx,targetid)){}
            for(i=0;i            {
                while(!QIn(&Qlinecanrx,RxMessage.Data[i])){}
            }
        }

    }
  CAN_ITConfig(CAN_IT_FMP0, ENABLE); //中断退出
}
void USB_HP_CAN_TX_IRQHandler(void)
{
    CAN_ClearITPendingBit(CAN_IT_RQCP0);
    CAN_ClearITPendingBit(CAN_IT_RQCP1);
    CAN_ClearITPendingBit(CAN_IT_RQCP2);
    CAN_ITConfig(CAN_IT_TME, DISABLE);
    CANSendStr();   //时刻查询是否可以给上位发送数据
}

void CANSendStr()
{
    CanTxMsg TxMessage;
    TxMessage.StdId=PCL_ID+bmqnum;  //用来设定标准标识符,0x08+2=0x0A
    TxMessage.ExtId=0;              //用来设定扩展标识符
  TxMessage.RTR=CAN_RTR_DATA;     //用来设定待传输消息的帧类型,它可以设置为数据帧或者远程帧,使用数据帧
  TxMessage.IDE=CAN_ID_STD;       //用来设定消息标识符的类型,使用标准标识符
  TxMessage.DLC = 8;              //用来设定待传输消息的帧长度,它的取值范围是0到0x8
    //20160822----zhang
    TxMessage.RTR=CAN_RTR_DATA;    //数据帧
    //20160822----zhang
    TxMessage.Data[0]='~';
    TxMessage.Data[1]='0';
    TxMessage.Data[2]='1';
    TxMessage.Data[3]='2';
    TxMessage.Data[4]='3';
    TxMessage.Data[5]='4';
    TxMessage.Data[6]='5';
    TxMessage.Data[7]='6';             
    CAN_Transmit(&TxMessage);
    CAN_ITConfig(CAN_IT_TME, ENABLE); //TransmitMailbox empty,发送中断在CAN_Transmit()后才能打开,用来判断发送完毕发送下一个数据 
}

6.使用中先使用CANSendStr()发送一条数据,则发送完毕后进入发送空中断,则之后会循环发送数据

参考文章:

http://www.openedv.com/thread-38867-1-1.html

http://www.stmcu.org/module/forum/thread-565605-1-1.html

http://www.cnblogs.com/chris-cp/p/3961508.html

http://www.openedv.com/thread-51889-1-1.html


关键字:STM32  CAN  接收和发送 引用地址:STM32--CAN简单接收和发送

上一篇:STM32的CAN总线学习总结
下一篇:STM32之CAN通信

推荐阅读最新更新时间:2024-03-16 16:12

ST发布STSAFE-A100评估套件,扩大STM32 Nucleo生态系统
意法半导体发布了STSAFE-A100评估套件,将进一步扩大STM32 Nucleo生态系统的丰富资源,加快安全单元的集成设计,利用可复用源代码以简化安全物联网设备、医疗探针等高价耗材、IT配件和消费产品的开发设计流程。 该评估套件包括集成STSAFE-A100安全单元的X-NUCLEO-STSA100扩展板和STSW-STSA100软件包。软件包括设备驱动程序、STM32微控制器源代码和STSAFE-A100的用例源代码,包括品牌和生态系统保护、设备注册和安全云连接等用例。 STSAFE-A100是一款便于使用的8引脚安全单元,可为主机系统提供稳健的不可变的硬件身份验证和安全数据管理服务,具有极强的网络攻击防御能力
[单片机]
ST发布STSAFE-A100评估套件,扩大<font color='red'>STM32</font> Nucleo生态系统
STM32】HAL库 STM32CubeMX教程四---UART串口通信详解
前言: 今天我们学习STM32CubeMX串口的操作,以及HAL库串口的配置,我们会详细的讲解各个模块的使用和具体功能,并且基于HAL库实现Printf函数功能重定向,UART中断接收,本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1、芯片: STM32F407ZET6 2、STM32CubeMx软件 3、IDE: MDK-Keil软件 4、STM32F1xx/STM32F4xxHAL库 5、串口: 使用USART1 PA9,PA10 知识概括: 通过本篇博客您将学到: STM32CubeMX创建串口例程 HAL库UATR函数库
[单片机]
【<font color='red'>STM32</font>】HAL库 STM32CubeMX教程四---UART串口通信详解
基于CAN总线的电车漏电检测装置的研制
0 引 言     由于石油资源的日益紧缺和人们环保意识的提高,新型动力交通工具不断涌现,如:氢燃料汽车、乙醇燃料汽车等,其中以电能作动力的环保型交通工具发展更为迅速。载有蓄电池的无轨电车是最具发展潜力的公共交通工具,它除了具有电车的优点以外,还省去了架设部分供电线路的优点,对美化城市起到极其重要的作用。据资料显示,北京在2008年就有近800辆的这种“准”无轨电车投入运营。然而,由于这样大型的电车内部蓄电池数量非常多,供电电压达到500 V之高,所以绝缘和漏电的处理技术一直是困扰电车开发人员的一大难题。目前,电车供电系统采用了多重逆变技术,把低压24 V供电与高压电动机驱动部分、大型充电机部分进行严格隔离,并安装了与大地接触的放
[嵌入式]
使用gcc工具链进行Linux环境下的stm32开发
处于好奇和学习Linux的目的,准备开始在虚拟机VMware的Ubuntu9.10操作系统下搭建stm32的开发环境。整个过程包括:安装gcc工具链---- 建立工程目录--- 编写Makefile,连接文件--- 编译生成可执行文件--- 下载测试。 我的工程资源:http://download.csdn.net/detail/xiaoxiaoxingkongo/9732047 工程建立参考连接:http://blog.csdn.net/embbnux/article/details/17616809 烧录参考链接:http://blog.csdn.net/ybhuangfugui/article/details/52597
[单片机]
stm32 串口9位数据
STM32可以一次发送9位数据,在此做一下简单说明。 一般不带奇偶校验位的串口数据:起始位(1)+数据位(8)+停止位(1) 带奇偶校验位的串口数据:起始位(1)+数据位(8)+校验位(1)+停止位(1) 如果数据位为9位,即:起始位(1)+数据位(9)+停止位(1) 9位数据STM8串口的配置:UART1_DeInit();//波特率9位1位停止位无奇偶校验同步时钟关发送接收使能 UART1_Init((u32)1000000,UART1_WORDLENGTH_9D,UART1_STOPBITS_1,UART1_PARITY_NO,UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TXRX_ENAB
[单片机]
STM32CAN系列经验总结
CAN是Controller Area Network的缩写,由德国博世公司开发;CAN通过ISO11891以及ISO11519进行了标准化; CAN总线的特点: 1、多主控制 在总线空闲时,所有单元都可以开始发送消息(多主控制); 最先访问总线的单元获得发送权(辨别方式:“CSMA/CA方式”); 多个单元同时开始发送时,发送高优先级ID消息的单元可获得发送权; 2、消息的发送 线相连的单元都可以开始发送新消息。两个以上的单元同时开始发送消息时,根据标识符(ID)决定优先级。ID并不是表示发送消息的目的地址,而是表示访问总线的消息优先级。两个以上的单元同时开始发送消息时,对各消息ID的每个位进行逐个仲裁比较,仲裁获胜(优先级
[单片机]
Scantinel开发突破性FMCW激光雷达 可降低计算量成本
激光雷达技术被认为是自动驾驶汽车的关键技术,而调频连续波(FMCW)激光雷达将促进自动驾驶技术的突破。有专家称,FMCW激光雷达最终将会取代目前的飞行时间(ToF)激光雷达系统。据外媒报道,德国激光雷达公司Scantinel Photonics得到了ZEISS Ventures(蔡司风险投资)的投资,据称是FMCW激光雷达领域唯一的欧洲公司。 (图片来源:Scantinel ) 激光雷达与雷达都用于通过分析反射波模式探测和测量距离。然而与雷达相比,FMCW激光雷达不使用无线电波,而是使用激光形式的光,因此能够提供更高的图像分辨率和更优的物体检测性能。此种FMCW激光雷达技术与传统方法相比具有显著的优势。 射程达25
[汽车电子]
S<font color='red'>can</font>tinel开发突破性FMCW激光雷达 可降低计算量<font color='red'>和</font>成本
STM32单片机对TFTLCD的驱动设计
看了TFTLCD和FSMC(灵活的静态存储控制器)的简介,还是一知半解,不知所云。 TFTLCD使用80并口,80 并口有如下一些信号线: CS: TFTLCD 片选信号。 WR:向 TFTLCD 写入数据。 RD:从 TFTLCD 读取数据。 D[15: 0]: 16 位双向数据线。 RST:硬复位 TFTLCD。 RS:命令/数据标志( 0,读写命令; 1,读写数据)。 只是记住FSMC在使用的时候要初始化和使能就行了。 关于lcd.c这个文件竟然接近3000行,好吧,我是写不出来,只能在主函数里调用了。 main.c: intmain(void) { u8x=0; u8lcd_id[12];//存放LCDID字符串
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved