打印
[国产单片机]

AT32双路CAN通信

[复制链接]
450|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1.1           案例 CAN通信
1.1.1       简介
CAN是控制器局域网络(Controller Area Network)的简称,是由德国BOSCH公司开发的,并最终成为国际标准,是国际上应用最广泛的现场总线之一。CAN具有高性能和高可靠性,已经被广泛应用于工业自动化、船舶、汽车、工业设备等方面。
AT32F437 CAN主要具有以下特性:
―  支持CAN协议2.0A和2.0B.
―  软件触发或者外部触发转换波特率最高可达1M bit/s
―  支持时间触发通信
―  中断使能和屏蔽
―  自动重传功能可配
发送
―  3个发送邮箱
―  发送优先级可配置
―  支持发送时间戳
接收
―  2个深度为3的FIFO
―  28组过滤器组
―  支持标识符列表模式
―  支持标识符掩码模式
―  支持FIFO溢出管理
―  时间触发通信模式
―  16位定时器
―  发送时间戳

AT32 SUFR板载了两颗CAN芯片,型号为SN65HVD230DR,在测试时需要注意正确设置跳线帽,以及将两颗CAN芯片的H和L信号线分别对接在一起。


1.1.2       资源准备
    硬件环境:
对应产品型号的AT-SURF-F437 Board
    软件环境:
AT32F435_437_Firmware_Library_V2.x.x\project\at_sufr_f437\examples\can

1.1.3       硬件设计
本案例使用的硬件资源有TFTLCD液晶显示屏、两颗SN65HVD230DR CAN芯片,对应的引脚如下:
表12. 硬件资源使用
   
编号
   
PIN Name
外设功能
备注
1
PB8
CAN1 RX
CAN1接收
2
PB9
CAN1 TX
CAN1发送
2
PB12
CAN2 RX
CAN2接收
4
PB13
CAN2 TX
CAN2发送

对应的电路原理如下:



1.1.4       软件设计
1)     CAN通讯测试
   初始化TFT LCD
   初始化CAN1 和 CAN2
   CAN1发送数据给CAN2,CAN2发送数据给CAN1
2)     代码介绍
main函数代码描述
int main(void)
{
  uint32_t cnt = 0;

  /* 初始化系统时钟*/  
  system_clock_config();  

  /* 初始化中断优先级分组*/   
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

  /* 初始化延时函数 */
  delay_init();

  /* 初始化LCD */
  lcd_init(LCD_DISPLAY_VERTICAL);

  /* can 1 初始化 */
  can_init(CAN1);

  /* can 2 初始化 */
  can_init(CAN2);

  /* 显示信息*/  
  lcd_string_show(10, 20, 200, 24, 24, (uint8_t*)"CAN Test");

  while(1)
  {
    /* can 1 数据初始化 */
    can_data_init(CAN1);

    /* 通过 can 1 发送数据 */
    can_transmit_data(CAN1,can1_tx_message);  

    /* can 2 数据初始化 */
    can_data_init(CAN2);

    /* 通过 can 2 发送数据 */
    can_transmit_data(CAN2, can2_tx_message);

    /* can 1 接收到数据 */
    if(can1_rx_flag != 0)
    {
      /* 清除can 1接收数据标志 */
      can1_rx_flag = 0;

      /* 显示标题 */
      lcd_string_show(10, 60, 200, 24, 24,(uint8_t *)"can 1 received");

      /* 显示filterindex */
      lcd_string_show(10, 100, 200, 24, 24,(uint8_t *)"filter_index:");
      lcd_num_show(170, 100, 200, 24, 24,can1_rx_message.filter_index, 1);

      if (can1_rx_message.id_type ==CAN_ID_EXTENDED )
      {
        /* 显示extended id*/
        lcd_string_show(10, 130, 200, 24, 24,(uint8_t *)"extended_id:");
        lcd_num_show(170, 130, 200, 24, 24,can1_rx_message.extended_id, 1);
      }
      else
      {
        /* 显示standard id*/
        lcd_string_show(10, 130, 200, 24, 24,(uint8_t *)"standard_id:");
        lcd_num_show(170, 130, 200, 24, 24,can1_rx_message.standard_id, 1);        
      }

      if (can1_rx_message.frame_type ==CAN_TFT_REMOTE )
      {
        /* 无数据 */
        lcd_string_show(10, 160, 200, 24, 24,(uint8_t *)"remote frame: no data");
      }
      else
      {
         /* 数据比较 */
        if(buffer_compare(can2_tx_message.data,can1_rx_message.data, 8) == 0)
        {
          /* 数据成功接收 */
          lcd_string_show(10, 160, 310, 24, 24,(uint8_t *)"can 1 数据成功接收");
        }
        else
        {
          /* 数据接收错误 */
          lcd_string_show(10, 160, 310, 24, 24,(uint8_t *)"can 1 数据接收错误");
        }
      }
    }

    /* can 2 接收到数据 */
    if(can2_rx_flag != 0)
    {
      /* 清除can 2接收数据标志 */
      can2_rx_flag = 0;

      /* 显示标题 */
      lcd_string_show(10, 220, 200, 24, 24,(uint8_t *)"can 2 received");

      /* 显示filterindex */
      lcd_string_show(10, 260, 200, 24, 24,(uint8_t *)"filter_index:");
      lcd_num_show(170, 260, 200, 24, 24,can2_rx_message.filter_index, 1);

      if (can2_rx_message.id_type ==CAN_ID_EXTENDED )
      {
        /* 显示extended id*/
        lcd_string_show(10, 290, 200, 24, 24,(uint8_t *)"extended_id:");
        lcd_num_show(170, 290, 200, 24, 24,can2_rx_message.extended_id, 1);
      }
      else
      {
        /* 显示standard id*/
        lcd_string_show(10, 290, 200, 24, 24,(uint8_t *)"standard_id:");
        lcd_num_show(170, 290, 200, 24, 24,can2_rx_message.standard_id, 1);        
      }

      if (can2_rx_message.frame_type == CAN_TFT_REMOTE)
      {
        /* 无数据 */
        lcd_string_show(10, 320, 200, 24, 24,(uint8_t *)"remote frame: no data");
      }
      else
      {
         /* 数据比较 */
        if(buffer_compare(can1_tx_message.data,can2_rx_message.data, 8) == 0)
        {
         /* 数据成功接收 */
          lcd_string_show(10, 320, 310, 24, 24,(uint8_t *)"can 2 数据成功接收");
        }
        else
        {
          /* 数据接收错误 */
          lcd_string_show(10, 320, 310, 24, 24,(uint8_t *)"can 2 数据接收错误");
        }
      }
    }

    cnt++;

    /* 显示传输次数 */
    lcd_string_show(10, 380, 200, 24, 24,(uint8_t *)"transfer number:");
    lcd_num_show(206, 380, 250, 24, 24, cnt,1);
    delay_ms(1000);
  }
}


void can_init(can_type *can_x)函数代码描述
/**
  * @brief initialize can.
  * @param can_x: select the can peripheral.
  *        this parameter can be one of the following values:
  *        CAN1, CAN2.
  * @retval none
  */
void can_init(can_type *can_x)



voidcan_transmit_data(can_type *can_x, can_tx_message_type tx_message_struct)函数代码描述
/**
  * @brief can transmit data
  * @param can_x: select the can peripheral.
  *        this parameter can be one of the following values:
  *        CAN1, CAN2.
  *        tx_message_struct: transmitmessage
  * @retval none
  */
void can_transmit_data(can_type *can_x,can_tx_message_type tx_message_struct)






1.1.5       下载验证
1) CAN1发送数据给CAN2,CAN2发送数据给CAN1
2) CAN1和CAN2收到数据后,对比收到数据是否正确
3) 在LCD屏上显示通讯信息
图29. 实验效果



使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

69

主题

119

帖子

5

粉丝