1 简介
GXR系列高精度程控电阻,可通过USB串口进行控制,内部USB转串口采用的CH340芯片,将USB连到电脑即可进行命令控制,但在某些情况下需要用单片机进行自动控制时,可以将GXR的USB口接到具有USB接口的单片机,通过单片机进行控制。本文以STM32F4为例,将STM32F4配置为USB HOST,与CH340通信,从而控制GXR程控电阻。
2 方法
2.1 生成基础工程
打开CubeMX,选择芯片为STM32F405RGT6。配置一个串口用于调试打印,配置USB_FS接口,模式为Host_Only,开启USB中断。
然后选择Middleware,开启USB_HOST,选择class为Virtual Port Com,调试阶段可以选择DEBUG_LEVEL为3,打印所有调试信息,调试完成再将DEBUG_LEVEL改为0,关闭调试打印。
回到system配置,开启SWD接口。
时钟选择外部晶体。
切换到时钟配置页,修改晶体频率为8MHz。
生成工程,生成后编译器选择V6版本,可大幅提高编译效率;优化等级调整为0,避免前期调试优化错误。
生成的工程无法直接访问CH340,需要进行如下修改。
2.2 修改 usbh_cdc.h文件
将宏定义 USB_CDC_CLASS 的值修改为 0xFF。
2.3 修改usbh_cdc.c文件
1)修改函数 USBH_CDC_InterfaceInit 中两处USBH_FindInterface调用参数:
第一处:
// interface = USBH_FindInterface(phost, COMMUNICATION_INTERFACE_CLASS_CODE,
// ABSTRACT_CONTROL_MODEL, COMMON_AT_COMMAND);
interface = USBH_FindInterface(phost, 0xFF, 0x01, 0x02);
第二处:
// interface = USBH_FindInterface(phost, DATA_INTERFACE_CLASS_CODE,
// RESERVED, NO_CLASS_SPECIFIC_PROTOCOL_CODE);
interface = USBH_FindInterface(phost, 0xFF,
0x01, VENDOR_SPECIFIC);
2)修改函数 USBH_CDC_ClassRequest ,将GetLineCoding 改为 SetLineCoding:
// status = GetLineCoding(phost, &CDC_Handle->LineCoding);
status = SetLineCoding(phost, &CDC_Handle->LineCoding);
3)修改函数 SetLineCoding ,在return上面新增两行波特率控制:
phost->Control.setup.d8[0] = 0x000ca140; //gxdaq add
phost->Control.setup.d8[1] = 0x0000cc03; //gxdaq add
3)修改main.c文件
最后修改main,添加串口重定向和USB通信测试。
1)添加头文件和外部变量:
#include <stdio.h>
#include "usbh_cdc.h"
extern USBH_HandleTypeDef hUsbHostFS;
2)串口重定向,arm V6编译器的串口重定向代码(V5编译器的有点区别,网上很多分享的,如STM32 printf 方法重定向到串口UART - Milton - 博客园):
/* ------------------通过重定向将printf函数映射到串口1上-------------------*/
#if !defined(__MICROLIB)
//#pragma import(__use_no_semihosting)
__asm (".global __use_no_semihosting\n\t");
void _sys_exit(int x) //避免使用半主机模式
{
x = x;
}
//__use_no_semihosting was requested, but _ttywrch was
void _ttywrch(int ch)
{
ch = ch;
}
FILE __stdout;
#endif
#if defined ( __GNUC__ ) && !defined (__clang__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
/* 实现串口发送一个字节数据的函数 */
while((USART1->SR&0X40)==0);
USART1->DR = (uint8_t) ch;
return ch;
}
3)变量定义,用于USB收发控制:
unsigned char recv_buf[100]={0};
uint32_t count = 0;
4)修改main函数中while(1),2秒设置一次电阻值,并且将接收到信息打印出来:
while (1)
{
/* USER CODE END WHILE */
MX_USB_HOST_Process();
/* USER CODE BEGIN 3 */
HAL_Delay(1);
count++;
if((count%2000) == 0)
{
USBH_CDC_Transmit(&hUsbHostFS,(uint8_t*)"set 10k\r\n",9);
}
if(USBH_CDC_Receive(&hUsbHostFS,recv_buf,100)==USBH_OK)
{
if(recv_buf[0]!=0)
{
printf("%s",recv_buf);
for(int i = 0; i < 100; i++)
{
recv_buf[i] = 0;
}
}
}
}
串口打印如下:
通过上述修改即可实现单片机USB HOST控制GXR程控电阻,便于实现自动控制。
示例工程:https://download.youkuaiyun.com/download/bingwueyi/89931191