stm32---CAN通信

发布者:心灵之窗最新更新时间:2020-03-26 来源: eefocus关键字:stm32  CAN通信  初始化 手机看文章 扫描二维码
随时随地手机看文章

can.c


#include "can.h"

 

/*************************************************************

函数名:CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)

功能: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

//返回值:0,初始化OK;

//    其他,初始化失败;

**************************************************************/

void CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    CAN_InitTypeDef CAN_InitStructure;

    CAN_FilterInitTypeDef CAN_FilterStructure;

#if CAN_RX0_INT_ENABLE 

    NVIC_InitTypeDef        NVIC_InitStructure;

#endif

    //1*开启CAN时钟和对应引脚时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    

    //2*引脚初始化配置

    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);

    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_InitStructure.CAN_Prescaler = brp; //分频系数为brp+1

    CAN_InitStructure.CAN_Mode=mode; //模式设置

    CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围

    CAN_InitStructure.CAN_BS2=tbs2; //Tbs2范围

    CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度的

    CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理

    CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒

    CAN_InitStructure.CAN_NART=ENABLE;  //使用报文自动传输

    CAN_InitStructure.CAN_RFLM=DISABLE;  //报文不锁定,新的覆盖旧的

    CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式

    CAN_InitStructure.CAN_TXFP=DISABLE;//优先级由报文标识符决定 

    CAN_Init(CAN1,&CAN_InitStructure);

    

    //4*过滤器初始化配置

    CAN_FilterStructure.CAN_FilterNumber =0; //过滤器0

    CAN_FilterStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //掩码模式,缺点是有误差,报表模式缺点是可识别ID少

    CAN_FilterStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位

    CAN_FilterStructure.CAN_FilterIdHigh=0x0000; //32位ID

    CAN_FilterStructure.CAN_FilterIdLow = 0x0000;

    CAN_FilterStructure.CAN_FilterMaskIdHigh=0x0000; //32位掩码

    CAN_FilterStructure.CAN_FilterMaskIdLow=0x0000;

    CAN_FilterStructure.CAN_FilterFIFOAssignment=CAN_FilterFIFO0;//过滤器0关联到FIFO0(邮箱0)

    CAN_FilterStructure.CAN_FilterActivation=ENABLE;//激活过滤器0

    CAN_FilterInit(&CAN_FilterStructure);//滤波器初始化

 

    #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;     // 主优先级为1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    #endif

}

 

    #if CAN_RX0_INT_ENABLE  //使能RX0中断

    //中断服务函数                

    void USB_LP_CAN1_RX0_IRQHandler(void)

    {

        CanRxMsg RxMessage;

        int i=0;

        CAN_Receive(CAN1, 0, &RxMessage);

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

        printf("rxbuf[%d]:%drn",i,RxMessage.Data[i]);

    }

    #endif

    

 

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)   

//len:数据长度(最大为8)                     

//msg:数据指针,最大为8个字节.

//返回值:0,成功;

//       其他,失败;

u8 CAN_Send_Msg(u8 *msg,u8 len)

{

    u16 i=0;

    u8 mbox;

    

    CanTxMsg TxMessage; 

    TxMessage.StdId=0x12; //标准ID,设置为扩展时自动变0

    TxMessage.ExtId=0x12; //扩展ID

    TxMessage.IDE=0; //决定是标准(1)还是扩展模式(0)

    TxMessage.RTR=0; //表明是数据帧(0)还是遥控帧(1),当是遥控帧时TxMessage.Data为0

    TxMessage.DLC=len; //数据长度(最大为8) 

    for(i=0;i        TxMessage.Data[i] = msg[i];

    

    mbox = CAN_Transmit(CAN1,&TxMessage); //发送数据,返回所使用邮箱的号码,如果没有空邮箱返回 CAN_NO_MB

    i=0;

    while((CAN_TransmitStatus(CAN1,mbox)==CAN_TxStatus_Failed)&&(i<0xfff)) i++; //发送完退出,未发送完i自加到0xfff时强制退出

    if(i>=0xfff) return 1; //失败

    return 0; //成功

}

 

 

//can口接收数据查询

//buf:数据缓存区;     

//返回值: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        buf[i] = RxMessage.Data[i];

    return RxMessage.DLC;//返回接收的数据长度

}

can.h


#ifndef _can_H

#define _can_H

 

#include "system.h"

 

 

void CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);

u8 CAN_Send_Msg(u8 *msg,u8 len);

u8 CAN_Receive_Msg(u8 *buf);

 

#endif

main.c


#include "system.h"

#include "SysTick.h"

#include "led.h"

#include "usart.h"

#include "can.h"

#include "key.h"

int main()

{

    u8 i,j,key;

    u8 mode=0; //默认是正常模式

    u8 res;

    u8 tbuf[8],char_buf[8];

    u8 rbuf[8];

    

    SysTick_Init(72);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组

    LED_Init();

    USART1_Init(9600);

    KEY_Init();

    

    CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_Normal);

    

    while(1)

    {   

        key =KEY_Scan(0);

        if(key==KEY_UP) //切换模式

        {

            mode = !mode; //模式切换,正常模式0x00,环回模式0x01

            CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,mode);

            if(mode==0) 

                printf("Normal Modern");//正常模式

            else

                printf("LoopBack Modern");//环回模式

        }

        else if(key==KEY_DOWN)//发送接收数据

        {

            for(j=0;j<8;j++)

            {

                tbuf[j] = j;

                char_buf[j] = tbuf[j]+0x30;//加0x30变ASC码

            }

            res = CAN_Send_Msg(tbuf,8); //返回0成功

            if(res)

                printf("Send Failedrn");

            else

                printf("发送数据:%srn",char_buf);

        }

        res = CAN_Receive_Msg(rbuf); //返回0失败,非0为接收数据长度

        if(res) //res不为0就可进入

        {

            for(j=0;j            {

                char_buf[j] = rbuf[j]+0x30; //加0x30变ASC码

            }

            printf("接收数据:%srn",char_buf);

        }

        i++;

        if(i%20==0)

        {

            led1=!led1;

        }

        

        delay_ms(10);

            

    }

}

关键字:stm32  CAN通信  初始化 引用地址:stm32---CAN通信

上一篇:stm32---SPI与外部FLASH
下一篇:stm32---RS485半双工通信

推荐阅读最新更新时间:2024-11-17 16:53

014_STM32程序移植之_L298N电机驱动模块
更改注意: STM32程序移植之L298N电机驱动模块 引脚连接图 STM32引脚 L298N引脚 功能 PA6 ENA 马达A的PWM PA7 ENB 马达B的PWM PA2 IN1 控制马达A PA3 IN2 控制马达A PA4 IN3 控制马达B PA5 IN4 控制马达B 注意 电源输入12V L298N的资料在这里 程序移植,刚才已经移植成功了,上面的是资料 注意,控制PWM 控制方向 在第二点的资料中只有IN1和IN2是因为原理是一样的,L298N总共有两个输出,所有有两个PWM输入还有IN1到IN
[单片机]
014_STM32程序移植之_L298N电机驱动模块
STM32单片机-CorTexM3位带操作的理解
一、STM的位带 STM32支持了位带操作(bit_band),有两个区中实现了位带。其中一个是SRAM 区的最低1MB范围,第二个则是片内外设区的最低1MB范围。这两个区中的地址除了可以像普通的RAM一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32 位的字。 每个比特膨胀成一个32 位的字,就是把1M扩展为32M , 于是RAM地址 0X200000000(一个字节)扩展到8个32 位的字,它们是:(STM32中的SRAM依然是8位的,所以RAM中任一地址对应一个字节内容) 0X220000000 ,0X220000004,0X220000008,0X22000000C,0X220000010,
[单片机]
<font color='red'>STM32</font>单片机-CorTexM3位带操作的理解
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
[单片机]
STM32学习——EXTI外部中断
EXTI简介 EXTI可以实现对外部输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。 可以看到EXTI一共有20条信号线,即可同时检测来自20路的中断请求。 代码实现 (1)首先配置GPIO初始化结构体 GPIO要配置为浮空输入 void Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStruc
[单片机]
<font color='red'>STM32</font>学习——EXTI外部中断
基于STM32设计的宠物投喂器
1. 前言 随着物联网技术的快速发展,智能家居已经进入人们的日常生活中,在政策加持的背景下,智能家居企业越来越关注相关技术的研发和应用;但是市场上的宠物投喂装置已经难以满足宠物主人的需求。文章介绍的宠物智能投喂装置是以STM32为核心,多个模块协调配合,共同完成针对不同年龄段的宠物进行定时定量投喂及实时环境监测与高温报警、以及主人随时可以通过智能设备了解宠物生活环境、为宠物加餐等功能。该系统的功能完善、价格低廉,使用方便,解决了宠物饲养者外出时的后顾之忧,还能保证宠物的进食有一定的规律性。 设计了一个宠物投喂器,支持手动控制粮食投喂,设置恒温阀值,定时投喂、温度、湿度实时显示、剩余粮食重量等功能。 2. 需求 做一个基于S
[单片机]
基于<font color='red'>STM32</font>设计的宠物投喂器
STM32开启USB CDC实现VCP功能
实现了一个 USB CDC的功能,让板子接收电脑端的字元控制板上 LED 的亮灭 1. 打开 CubeMx, 搜索STM32F407VG, 选中找打的芯片, 然后点击右上角的 按钮. 2 设置晶振 3. USB 点选 Device(FS),这个是开启 USB 功能 5. 打开 usbd_cdc_if.c 档案,找到里头的 CDC_Receive_FS() 函数 编译程序并烧录到芯片,当板子上面的 USB 口插上电脑后出现了一个虚拟串口. span font-size:14px;white-space:normal;background-color:#ffffff; = style= overflow-wrap: bre
[单片机]
<font color='red'>STM32</font>开启USB CDC实现VCP功能
基于STM32设计的智能空调
一、项目背景 随着人们生活水平的不断提高,对居住环境的舒适度要求也越来越高。空调作为一种重要的家电设备,已经成为了现代家庭中必不可少的一部分。本文介绍了一种基于STM32的智能空调设计方案,可以自动地根据环境温度进行温度调节。 二、设计思路 2.1 整体构架 智能空调系统由温度检测传感器、微控制器、OLED显示屏、按键及直流电源等组件构成。传感器用于检测环境温度,通过微控制器进行处理后,将结果输出到OLED显示屏上展示。按键可根据需求调整预设阀值,切换模式等操作。 2.2 硬件设计 (1)温度检测传感器 选择DS18B20数字温度传感器作为本系统的温度检测器件。该传感器具有精度高,响应速度
[单片机]
基于<font color='red'>STM32</font>设计的智能空调
stm32 驱动 触摸屏
由于智能手机的发展和大屏幕的兴起,触摸屏已经得到了广泛的应用。触摸屏分为两种:电阻触屏 俗称“软屏”;电容触屏俗称“硬屏”。 电阻触摸屏的屏体部分是一块多层复合薄膜,由一层玻璃或有机玻璃作为基层,表面涂有一层透明的阻性材料组成的导电层(ITO膜),上面再盖有一层外表面经过硬化处理、光滑防刮的塑料层。它的内表面也涂有一层ITO,在两层导电层之间有许多细小(小于千分之一英寸)的透明隔离点把它们隔开。当手指接触屏幕时,两层 ITO发生接触,电阻发生变化,控制器根据检测到的电阻变化来计算接触点的坐标,再依照这个坐标来进行相应的操作,因此这种技术必须是要施力到屏幕上,才能获得触摸效果。 所有的电阻式触摸屏都采用分压器原
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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