你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32H7体验】+CAN总线驱动程序

[复制链接]
305765986@qq.co 发布时间:2022-5-28 11:11
关于通信波特率设置、初始化程序、发送程序、接收程序
1、波特率
CAN通讯属于异步通讯,没有时钟信号线,所以所有节点之间要约定好使用相同的波特率来传输数据。波特率不同将无法进行通信
CAN总线是基于相同波特率通信的,所以设备接入前要知道总线上的波特率是多少。
波特率=(pclk1/((1+8+7)*9))=36MHz/16/9=250Kbits
在can.h文件中定义一些参数,用于计算波特率
2、数据数量
      一次最多只能发送8个字节的数据,这是由CAN协议规定的。
      多于8个的需要第二次再发送,或者做一个上层的连续多数据发送的函数。
      1       0  逻辑电平    用逻辑电平组成数据
3、初始化程序
  1. u8 CAN1_Configuration(void){ //CAN初始化(返回0表示设置成功,返回其他表示失败)  J) v- m; g. d6 h) B6 h
  2.     GPIO_InitTypeDef        GPIO_InitStructure; 7 K; I; ~+ y9 C& O; v" H
  3.     CAN_InitTypeDef         CAN_InitStructure;
    3 l* N* @0 S+ u/ j
  4.     CAN_FilterInitTypeDef   CAN_FilterInitStructure;
    3 ?; `+ t! D; h5 a; a; L& x! l( d

  5. + @1 Q0 F. Q0 ?$ B2 W2 C( D2 R$ F
  6. #if CAN_INT_ENABLE
    " L, u6 k( b% ^9 }# B0 X& B
  7.     NVIC_InitTypeDef        NVIC_InitStructure;         0 q, `; ^- ?0 u8 a* D
  8. #endif7 Q; L% [$ [# N
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //使能PORTD时钟                                                                4 k/ d! {/ b) C- v. q, x0 F8 M
  10.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);    //使能CAN1时钟  ) `  W3 z, J( B/ p; h) b  V: h
  11.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    $ u. W5 o  V5 D. a# M
  12.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      w( Q% ^* R" S3 n8 E8 T
  13.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽7 r, R! w* M1 p( @4 e& Z
  14.           GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO7 r3 ^' L5 ^! T$ o# P
  15.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    * o: }! Z7 O) J8 X8 d( ~3 Z
  16.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
    / Y' K% a* z3 p& ~/ [3 h
  17.           GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO2 c% m' r+ c- I# z1 k
  18.     //CAN单元设置
    2 {, W& c7 S) E( s$ \  F
  19.     CAN_InitStructure.CAN_TTCM=DISABLE;         //非时间触发通信模式  
    / C5 q! s3 _9 z; R" M3 O
  20.     CAN_InitStructure.CAN_ABOM=DISABLE;         //软件自动离线管理   
      L7 K  X9 a3 A" E
  21.     CAN_InitStructure.CAN_AWUM=DISABLE;         //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位). V2 Q6 J/ s! K4 @. b7 i, Z
  22.     CAN_InitStructure.CAN_NART=ENABLE;          //禁止报文自动传送 ( i0 L; C; G1 f: t  a2 g* r/ ]2 y9 r
  23.     CAN_InitStructure.CAN_RFLM=DISABLE;         //报文不锁定,新的覆盖旧的  
    : s# j+ I! Z0 \
  24.     CAN_InitStructure.CAN_TXFP=DISABLE;         //优先级由报文标识符决定
    : B5 l7 ^- n; B5 ~7 a9 h* t) P
  25.     CAN_InitStructure.CAN_Mode= CAN_Mode_Normal;  //模式设置:CAN_Mode_Normal 普通模式,CAN_Mode_LoopBack 回环模式; / ?! R3 Q, `, S2 O6 }7 j* d
  26.     //设置波特率  \2 @1 o6 ?1 Y8 c0 G
  27.     CAN_InitStructure.CAN_SJW=tsjw;             //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq    CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
    ( V; F- B1 W: l$ \2 y" E
  28.     CAN_InitStructure.CAN_BS1=tbs1;             //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~ CAN_BS1_16tq# j% I8 F# T1 B# l. D- W  m
  29.     CAN_InitStructure.CAN_BS2=tbs2;             //Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq) A$ r) E* C1 M& r! p* [: u- i
  30.     CAN_InitStructure.CAN_Prescaler=brp;        //分频系数(Fdiv)为brp+1  
    ' ^* c  U6 n3 u4 T, k0 g
  31.     CAN_Init(CAN1, &CAN_InitStructure);         //初始化CAN1 1 f3 p. q0 {$ J: X' m7 O) c
  32.         //设置过滤器
    8 p8 x6 i' P: N5 E6 X$ V+ m9 G
  33.     CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
    ) U; O# o+ ]% @/ M/ v. A
  34.     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //屏蔽位模式' U0 c+ a* b) ~4 I9 J
  35.     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  //32位宽 - {# z+ x1 }  Y# `$ C  C) p
  36.     CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;    //32位ID
    . R, |& Y3 y% V0 q6 W& f* I/ z
  37.     CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
    1 y6 s, h- Q- Y* f! o1 s! y
  38.     CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
    ; p8 a0 g$ _9 O+ j6 Y  n3 {$ O- H5 b: S
  39.     CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
    $ F! M! D2 o6 g2 q
  40.     CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
    2 P9 u. N% Q9 c3 v, j- R, b
  41.     CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0: z* L% b' E7 n6 b
  42.     CAN_FilterInit(&CAN_FilterInitStructure);           //滤波器初始化
    ; }- C$ p4 T4 X& L  M" m3 x+ x5 ]

  43. 5 ]7 O  e1 Q' h  X$ t. y: @
  44. #if CAN_INT_ENABLE         //以下是用于CAN中断方式接收的设置" b7 n, ~; `3 `& X7 j4 F  r
  45.     CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);              //FIFO0消息挂号中断允许.            ! n/ w* n( k& d. t9 V5 A8 E$ ~
  46.     NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
    , k; Q8 |$ j6 U& H: o1 w
  47.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
    5 i! E7 V$ |& y; s
  48.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
    3 v2 U7 r- d0 T) e
  49.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;4 I9 t* ?& z' |0 P! Q
  50.     NVIC_Init(&NVIC_InitStructure);
    " J- e4 t+ V: X) P* E* f
  51. #endif
    3 m+ w: b3 P* l; t( N5 V
  52.     return 0;                5 j& P/ g+ |. \; Y5 \  ^5 T
  53. }
复制代码

0 s  B& F" `5 i" l" r. A
3、发送程序
  1. //CAN发送一组数据(固定格式:ID为0X12,标准帧,数据帧)   
    8 T) z! r5 H. e6 i% R( v
  2. //msg:数据指针,最大为8个字节,len:数据长度(最大为8) # @8 y6 e9 N0 |/ ~
  3. //返回值:0,成功; 其他,失败;2 P. L- t4 [# Y, e) y
  4. u8 CAN_Send_Msg(u8* msg,u8 len){   
    # {5 l6 C- z  j
  5.     u8 mbox;" a& S, i$ _$ M* ~: [
  6.     u16 i=0;: D  G: x: s2 l, a; W
  7.     CanTxMsg TxMessage;/ c  j- C- E) e4 E. ?
  8.     TxMessage.StdId=0x10;           // 标准标识符
    / i4 q! Y- X$ O5 [
  9.     TxMessage.ExtId=0x00;           // 设置扩展标识符& Y9 m# v- e* x8 H
  10.     TxMessage.IDE=CAN_Id_Standard;  // 标准帧
    8 x0 }& }" i1 G7 x
  11.     TxMessage.RTR=CAN_RTR_Data;     // 数据帧  v) w# s8 F, B; x7 l4 G
  12.     TxMessage.DLC=len;              // 要发送的数据长度; \5 J7 Q+ {, i! j& r) h
  13.     for(i=0;i<len;i++)7 F+ b3 b6 N5 M, @% y% n4 b, L& f
  14.     TxMessage.Data[i]=msg[i];       //写入数据              
    3 T- _% ~& x; {4 [6 m
  15.     mbox= CAN_Transmit(CAN1,&TxMessage);   - H0 A1 @9 T+ A& A
  16.     i=0;
    ' g6 X$ @! s& J7 V" J7 p& ~
  17.     while((CAN_TransmitStatus(CAN1,mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
    0 X8 R' S2 r9 @' Z
  18.     if(i>=0XFFF)return 1;: V# c% H9 L* }- ]
  19.     return 0;    ) x2 Y/ ]' `" R: _3 d/ P7 c
  20. }
复制代码

' k, T! M! @. \: y+ h) k
4、接收程序
  1. //can口接收数据查询
      d. e3 A1 u1 j, ]3 Z4 R1 ]( m
  2. //buf:数据缓存区;     + {$ k8 f' z6 M- C' t7 H  D& w
  3. //返回值:0,无数据被收到,其他,接收的数据长度;3 {3 h4 ]/ Q* a9 v! M: s' X
  4. u8 CAN_Receive_Msg(u8 *buf){                  
    2 t# e1 X8 W; F9 g% I
  5.     u32 i;
    , r, J, v% U+ |! z
  6.     CanRxMsg RxMessage;) f$ N$ T$ @/ s9 I
  7.     if(CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;//没有接收到数据,直接退出
    3 H9 V: y" M2 _! d8 }, R
  8.     CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//读取数据
    # ~' c; @& o' B  p1 S) a
  9.     for(i=0;i<8;i++) //把8个数据放入参数数组! E" |& a. N4 G4 r
  10.     buf[i]=RxMessage.Data[i];  
    ) K9 y% [" n9 X- z- K  k1 j
  11.     return RxMessage.DLC;  //返回数据数量
    : g4 ]; M; _- L7 }
  12. }
复制代码
8 \; q9 U* g- z: O. u8 W
STM32H7A3ZIQ作为主机、STM32F103C8T6作为从机。. W6 V* I9 s0 G1 F
主机通过CAN通信发送数据,从机接收数据,并显示在屏幕上。
& w9 @# L6 O$ S2 v( N  o
) p7 s$ ^( \! |5 u2 y" B-------结果展示------- 2.jpg , {2 I* J+ O. }5 S
3.jpg
收藏 评论0 发布时间:2022-5-28 11:11

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版