2310|5

6960

帖子

11

TA的资源

版主

楼主
 

【AT-START-F425测评】USB转CAN之二 [复制链接]

  本帖最后由 lugl4313820 于 2022-4-14 22:26 编辑

我的起始工程是基于RT_Thread CAN工程搭建的。

1、在原来的基础工程上添加USB工程的驱动:

从USB工程中拷贝usb_drivers、usbd_class、usbh_class三个文件夹到工程的\libraries\middlewares文件夹下面。

  2、在mdk工程中新加入文件:

 3、从原来的USB虚拟串口工程中拷贝usb_conf.h到user文件夹下:

4、在mdk中添加头文件的引用:

5、修改usb_delay_ms为rt_thread_mdelay,同时给头文件添加必要的地方添加rtthread.h头文件。

6、新建usb_port.c与usb_port.h文件

#include "usb_port.h"
#include "usb_conf.h"
#include "usb_core.h"
#include "usbd_int.h"
#include "cdc_class.h"
#include "cdc_desc.h"
#include "rtthread.h"
#include "usb_std.h"

otg_core_type otg_core_struct;
uint8_t usb_buffer[256];
void usb_clock48m_select(usb_clk48_s clk_s);
void usb_gpio_config(void);
void usb_low_power_wakeup_config(void);


/* usart global struct define */
extern linecoding_type linecoding;
void usb_usart_config(linecoding_type linecoding);
void usart_gpio_config(void);
#define  usart_buffer_size  1024
uint8_t usart_rx_buffer[usart_buffer_size];
uint16_t hw_usart_rx_index = 0;
uint16_t hw_usart_read_index = 0;
uint16_t usart_rx_data_len = 0;
uint16_t ov_cnt = 0;
void usart_send_data(uint8_t *send_data, uint16_t len);
uint16_t usart_receive_data(void);


void usb_usart_config( linecoding_type linecoding)
{
  usart_stop_bit_num_type usart_stop_bit;
  usart_data_bit_num_type usart_data_bit;
  usart_parity_selection_type usart_parity_select;

  /* enable the usart2 and gpio clock */
  crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, FALSE);
  crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, TRUE);
  
  /* stop bit */
  switch(linecoding.format)
  {
    case 0x0:
      usart_stop_bit = USART_STOP_1_BIT;
      break;
    /* to be used when transmitting and receiving data in smartcard mode */
    case 0x1:
      usart_stop_bit = USART_STOP_1_5_BIT;
      break;
    case 0x2:
      usart_stop_bit = USART_STOP_2_BIT;
      break;
    default :
      break;
  }
  /* data bits */
  switch(linecoding.data)
  {
    case 0x8:
      usart_data_bit = USART_DATA_8BITS;
      break;
    case 0x7:
      usart_data_bit = USART_DATA_7BITS;
      break;
    /* hardware usart not support data bits for 5/6/16 */
    case 0x5:
    case 0x6:
    case 0x10:
      break;
    default :
      break;   
  }
  /* parity */
  switch(linecoding.parity)
  {
    case 0x0:
      usart_parity_select = USART_PARITY_NONE;
      break;
    case 0x1:
      usart_parity_select = USART_PARITY_ODD;
      break;
    case 0x2:
      usart_parity_select = USART_PARITY_EVEN;
      break;
    /* hardware usart not support parity for mark and space */
    case 0x3:
    case 0x4:
      break;
    default :
      break;
  }

  nvic_irq_enable(USART2_IRQn, 0, 0);
  
  /* configure usart2 param */
  usart_init(USART2, linecoding.bitrate, usart_data_bit, usart_stop_bit);
  usart_parity_selection_config(USART2, usart_parity_select);
  usart_transmitter_enable(USART2, TRUE);
  usart_receiver_enable(USART2, TRUE);
  
  /* enable usart2 interrupt */
  usart_interrupt_enable(USART2, USART_RDBF_INT, TRUE);
  usart_enable(USART2, TRUE);
}

/**
  * @brief this function handles usart2 gpio config.
  * @param  none
  * @retval none
  */
void usart_gpio_config(void)
{
  gpio_init_type gpio_init_struct;   
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  
  /* configure the usart2 tx, rx pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_2 | GPIO_PINS_3;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOA, &gpio_init_struct);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE2, GPIO_MUX_1);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE3, GPIO_MUX_1);
}

/**
  * @brief  usb 48M clock select
  * @param  clk_s:USB_CLK_HICK, USB_CLK_HEXT
  * @retval none
  */
void usb_clock48m_select(usb_clk48_s clk_s)
{
  if(clk_s == USB_CLK_HICK)
  {
    crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);

    /* enable the acc calibration ready interrupt */
    crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);

    /* update the c1\c2\c3 value */
    acc_write_c1(7980);
    acc_write_c2(8000);
    acc_write_c3(8020);
    /* open acc calibration */
    acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
  }
  else
  {
    switch(system_core_clock)
    {
      /* 48MHz */
      case 48000000:
        crm_usb_clock_div_set(CRM_USB_DIV_1);
        break;

      /* 72MHz */
      case 72000000:
        crm_usb_clock_div_set(CRM_USB_DIV_1_5);
        break;

      /* 96MHz */
      case 96000000:
        crm_usb_clock_div_set(CRM_USB_DIV_2);
        break;

      default:
        break;

    }
  }
}

/**
  * @brief  this function config gpio.
  * @param  none
  * @retval none
  */
void usb_gpio_config(void)
{
  gpio_init_type gpio_init_struct;

  crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE);
  gpio_default_para_init(&gpio_init_struct);

  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;


#ifdef USB_SOF_OUTPUT_ENABLE
  crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK, TRUE);
  gpio_init_struct.gpio_pins = OTG_PIN_SOF;
  gpio_init(OTG_PIN_SOF_GPIO, &gpio_init_struct);
  gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_SOF_SOURCE, OTG_PIN_MUX);
#endif

  /* otgfs use vbus pin */
#ifndef USB_VBUS_IGNORE
  gpio_init_struct.gpio_pins = OTG_PIN_VBUS;
  gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
  gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX);
  gpio_init(OTG_PIN_GPIO, &gpio_init_struct);
#endif


}
#ifdef USB_LOW_POWER_WAKUP
/**
  * @brief  usb low power wakeup interrupt config
  * @param  none
  * @retval none
  */
void usb_low_power_wakeup_config(void)
{
  exint_init_type exint_init_struct;

  crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
  exint_default_para_init(&exint_init_struct);

  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
  exint_init_struct.line_select = OTG_WKUP_EXINT_LINE;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);
}

#endif

/**
  * @brief  this function handles otgfs interrupt.
  * @param  none
  * @retval none
  */
void OTG_IRQ_HANDLER(void)
{
  if(exint_flag_get(OTG_WKUP_EXINT_LINE))
  {
    exint_flag_clear(OTG_WKUP_EXINT_LINE);
  }
  usbd_irq_handler(&otg_core_struct);
}


void usb_init_port(void)
{

	
	 /* usart gpio config */
  usart_gpio_config();
	
	/* hardware usart config: usart2 */
  usb_usart_config(linecoding);
	
	/* usb gpio config */
  usb_gpio_config();
	
	  /* enable otgfs clock */
  crm_periph_clock_enable(OTG_CLOCK, TRUE);

  /* select usb 48m clcok source */
  usb_clock48m_select(USB_CLK_HEXT);

  /* enable otgfs irq */
  nvic_irq_enable(OTG_IRQ, 0, 0);

  /* init usb */
  usbd_init(&otg_core_struct,
            USB_FULL_SPEED_CORE_ID,
            USB_ID,
            &cdc_class_handler,
            &cdc_desc_handler);
}


/**
  * @brief  this function handles usart2 send data.
  * @param  send_data: pointer to data
  * @param  len: data len
  * @retval none
  */
void usart_send_data(uint8_t *send_data, uint16_t len)
{
  uint16_t index = 0;
  for(index = 0; index < len; index++ )
  {
    do
    {
      ;
    }while(usart_flag_get(USART2, USART_TDBE_FLAG) == RESET);
    
    usart_data_transmit(USART2, send_data[index]);
  }
}

/**
  * @brief  this function handles usart2 receive data.
  * @param  none
  * @retval the data len
  */
uint16_t usart_receive_data(void)
{
  uint16_t usart_data_len;
  if(hw_usart_read_index == hw_usart_rx_index)
  {
		usart_data_len = 0;
  }
  else
  {
    /* whether to process the fifo overflow or not */
    if(hw_usart_rx_index > hw_usart_read_index)
      usart_data_len = hw_usart_rx_index - hw_usart_read_index;
    else if(hw_usart_rx_index == 0 && hw_usart_rx_index != hw_usart_read_index)
      usart_data_len = usart_buffer_size - hw_usart_read_index;
    else
      usart_data_len = (usart_buffer_size-1) + hw_usart_rx_index - hw_usart_read_index;
  }
  
  return usart_data_len;
}

/**
  * @brief  this function handles usart2 handler.
  * @param  none
  * @retval none
  */
void USART2_IRQHandler(void)
{
  if(usart_flag_get(USART2, USART_RDBF_FLAG) != RESET)
  {
    /* read one byte from the receive data register */
    usart_rx_buffer[hw_usart_rx_index] = usart_data_receive(USART2);
    hw_usart_rx_index = ( (hw_usart_rx_index+1) & (usart_buffer_size-1) );
  }
}

void usb_recv_test(void)
{
	uint16_t data_len;
	 uint32_t timeout;

  uint8_t send_zero_packet = 0;
	/* get usb vcp receive data */
    data_len = usb_vcp_get_rxdata(&otg_core_struct.dev, usb_buffer);
	
	/* send data to hardware usart */    
    if(data_len > 0)
    {
      usart_send_data(usb_buffer, data_len);
    }
     
    /* if hardware usart received data,usb send data to host */
    usart_rx_data_len = usart_receive_data();
    if(usart_rx_data_len || send_zero_packet == 1)
    {
      if(usart_rx_data_len > 0)
        send_zero_packet = 1;

      if(usart_rx_data_len == 0)
        send_zero_packet = 0;

      timeout = 500;
      
      if((hw_usart_read_index + usart_rx_data_len) < usart_buffer_size)   
      {
        do
        {
          /* send data to host */
          if(usb_vcp_send_data(&otg_core_struct.dev, &usart_rx_buffer[hw_usart_read_index], usart_rx_data_len) == SUCCESS)
          {
            hw_usart_read_index = hw_usart_read_index + usart_rx_data_len;
            
            break;
          }
        }while(timeout --);
        
      }
      /* process the fifo overflow */
      else
      {
        do
        {
          /* send data to host */
          if(usb_vcp_send_data(&otg_core_struct.dev, &usart_rx_buffer[hw_usart_read_index], usart_buffer_size - hw_usart_read_index) == SUCCESS)
          {
            /* get fifo overflow data count */
            ov_cnt = usart_rx_data_len - (usart_buffer_size - hw_usart_read_index);
            hw_usart_read_index = 0;
            break;
          }
        }while(timeout --);
        timeout = 50;
        do
        {
          /* send data to host */
          if(usb_vcp_send_data(&otg_core_struct.dev, &usart_rx_buffer[hw_usart_read_index], ov_cnt) == SUCCESS)
          {
            hw_usart_read_index = ov_cnt;
            break;
          }
        }while(timeout --);
      }
    }
  
}

usbpor.h

#ifndef _USB_PORT_H_
#define _USB_PORT_H_

#include "at32f425.h"
#include "at32f425_board.h"


void usb_init_port(void);
void usb_recv_test(void);
#endif

7、在main.c中引用usb_port.h头文件,添加usb初始化函数。

int main(void)
{
	can_configuration();
  usb_init_port();
  tid_rudder = rt_thread_create("RUDDER",
                            tid_rudder_entry, RT_NULL,
                            KEY_THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);
    /* 如果获得线程控制块,启动这个线程 */
    if (tid_rudder != RT_NULL)
        rt_thread_startup(tid_rudder);
		usart_send_data("hello\n",6);
		
  while(1)
  {
		usb_recv_test();
		rt_thread_mdelay(10);
//    at32_led_toggle(LED2);
//    rt_thread_mdelay(g_speed * DELAY);
//    at32_led_toggle(LED3);
//    rt_thread_mdelay(g_speed * DELAY);
//    at32_led_toggle(LED4);
//    rt_thread_mdelay(g_speed * DELAY);
		//can_transmit_data();
		//at32can_count.can_tx ++;
  }
}

至此所有usb驱动移植玩必,编译时有时会报一些引用函数的错误,一一找出来添回或按指定修改就OK。

【实验现象】连接USART2的TX引脚(PA2)和RX(PA3)

实验现象为:

 

 至此虚拟串口移植到CAN工程中已经完成。

下一步,修改串口与CAN的中转接口函数。

最新回复

看起来代码量不小。   详情 回复 发表于 2022-4-19 17:42
点赞 关注
 
 

回复
举报

6960

帖子

11

TA的资源

版主

沙发
 

rt_thread:占用内存情况:

 3.1.5 build Apr 14 2022
 2006 - 2020 Copyright by rt-thread team
hello
msh >
 \ | /
- RT -     Thread Operating System
 / | \     3.1.5 build Apr 14 2022
 2006 - 2020 Copyright by rt-thread team
hello
msh >
msh >
msh >free
total memory: 15336
used memory : 1700
maximum allocated memory: 1700
msh >
 

 
 
 

回复

7159

帖子

2

TA的资源

版主

板凳
 

手把手教学系列篇,希望能看到成品~

 
 
 

回复

308

帖子

0

TA的资源

纯净的硅(初级)

4
 

用RT-Thread做确实很方便,强!👍👍

 
 
 

回复

11

帖子

0

TA的资源

一粒金砂(中级)

5
 

单片机上做大而全的RTOS,我不喜欢,所以,也不喜欢RTT。

AT32的2.x版本的库,好像是抄GD32的,也不喜欢,还是喜欢原来1.x.x的库。

 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

6
 

看起来代码量不小。

个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

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