📄 ch372drv.c
字号:
/*
; 单片机内置USB调试固件程序 V1.0
; 用于连接CH372或者CH375的单片机进行简单的调试功能
; 可以用include直接包含到应用系统的主程序中,或者添加到工程项目中
;
; Website: http://winchiphead.com
; Email: tech@winchiphead.com
; @2004.08
;****************************************************************************
*/
// ------------------------------------------------------------------------------------------------------
/********************************************************************************************************
** CH372芯片说明
** CH372芯片占用两个地址位,当A0引脚为高电平时选择命令端口,可以写入命令;当A0引脚为低电平时选择数据端
** 口,可以读写数据。单片机通过8位并口对CH372芯片进行读写,所有操作都是由一个命令码、若干个输入数据和若干
** 个输出数据组成,部分命令不需要输入数据,部分命令没有输出数据。命令操作步骤如下:
** 1)在A0=1时向命令端口写入命令代码;
** 2)如果该命令具有输入数据,则在A0=0时依次写入输入数据,每次一个字节;
** 3)如果该命令具有输出数据,则在A0=0时依次读取输出数据,每次一个字节;
** 4)命令完成,可以暂停或者转到1)继续执行下一个命令。
** CH372芯片专门用于处理USB通讯,在接收到数据后或者发送完数据后,CH372以中断方式通知单片机进行处理。
** 单片机通过CH372接收数据的处理步骤如下:
** 1)当CH372接收到USB主机发来的数据后,首先锁定当前USB缓冲区,防止被后续数据覆盖,然后将INT#引脚设置为低
** 电平,向单片机请求中断;
** 2)单片机进入中断服务程序,首先执行GET_STATUS命令获取中断状态;
** 3)CH372在GET_STATUS命令完成后将INT#引脚恢复为高电平,取消中断请求;
** 4)由于通过上述GET_STATUS命令获取的中断状态是“下传成功”,所以单片机执行RD_USB_DATA命令从CH372读取接收到的数据;
** 5)
**
**
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
/* MCS-51单片机C语言, KC7.0 */
/* 用于其它类型单片机或者硬件资源不同时, 该程序应该根据需要进行局部修改 */
#include <c8051f020.h> // SFR declarations
#include "GlobeDef.h"
#include "CH372Drv.H"
#ifdef __CX51__
#ifndef __C51__
#define __C51__ 1
#endif
#endif
#ifdef __C51__
typedef unsigned char idata *PUINT8;
#else
typedef unsigned char *PUINT8;
#endif
#ifdef __C51__
typedef unsigned char xdata *PUINT8X;
#else
typedef unsigned char *PUINT8X;
#endif
#ifdef __C51__
typedef unsigned char code *PUINT8C;
#else
typedef unsigned char *PUINT8C;
#endif
#ifdef __C51__
#pragma NOAREGS
#endif
#ifndef MAX_DATA_SIZE
#define MAX_DATA_SIZE 56 // 单次命令处理的最大数据长度,有效值是1到56
#endif
#ifndef MAX_BUFFER_SIZE
#define MAX_BUFFER_SIZE MAX_DATA_SIZE+3 // 上传或下传缓冲区的最大长度(3代表命令码/状态码、命令反码和数据长度)
#endif
/* 上传或下传缓冲区索引定义 */
#define COMMAND_ID 0
#define COMMAND_NOT_ID 1
#define LENGTH_ID 2
#define DATA_START_ID 3
#define STATUS_ID 0
typedef USB_DOWN_BUFFER[MAX_BUFFER_SIZE]; // 计算机发给CH372的下传缓冲区定义
typedef USB_UP_BUFFER[MAX_BUFFER_SIZE]; // CH372发给计算机的上传缓冲区定义
/* 命令码定义 */
#define USB_CMD_GET_FW_INFO 0x00 // 返回固件程序版本,并取消未完成的上传数据块
#define USB_CMD_GET_APP_INFO 0x01 // 返回当前应用系统的版本和说明字符串
#define USB_CMD_GET_TEST_DATA 0x02 // 返回当前测试数据
#define USB_CMD_GET_ALL_PARAMS 0x10 // 返回所有参数的值(不包含流量修正系数)
#define USB_CMD_GET_PRESS_SET 0x11 // 返回参数设定压力
#define USB_CMD_GET_PRESS_MAX 0x12 // 返回参数压力上限
#define USB_CMD_GET_PRESS_MIN 0x13 // 返回参数压力下限
#define USB_CMD_GET_LEAK_MAX 0x14 // 返回参数流量上限
#define USB_CMD_GET_FILL_TIME 0x15 // 返回参数充气时间
#define USB_CMD_GET_TEST_TIME 0x16 // 返回参数测试时间
#define USB_CMD_GET_ALL_COEFS 0x20 // 返回所有流量修正值及其系数
#define USB_CMD_GET_COEF_1 0x21 // 返回第一段流量修正值及其系数
#define USB_CMD_GET_COEF_2 0x22 // 返回第二段流量修正值及其系数
#define USB_CMD_GET_COEF_3 0x23 // 返回第三段流量修正值及其系数
#define USB_CMD_GET_COEF_4 0x24 // 返回第四段流量修正值及其系数
#define USB_CMD_SET_ALL_PARAMS 0x80 // 修改所有参数的值(不包含流量修正系数)
#define USB_CMD_SET_PRESS_SET 0x81 // 修改参数设定压力
#define USB_CMD_SET_PRESS_MAX 0x82 // 修改参数压力上限
#define USB_CMD_SET_PRESS_MIN 0x83 // 修改参数压力下限
#define USB_CMD_SET_LEAK_MAX 0x84 // 修改参数流量上限
#define USB_CMD_SET_FILL_TIME 0x85 // 修改参数充气时间
#define USB_CMD_SET_TEST_TIME 0x86 // 修改参数测试时间
#define USB_CMD_SET_ALL_COEFS 0x90 // 修改所有流量修正值及其系数
#define USB_CMD_SET_COEF_1 0x91 // 修改第一段流量修正值及其系数
#define USB_CMD_SET_COEF_2 0x92 // 修改第二段流量修正值及其系数
#define USB_CMD_SET_COEF_3 0x93 // 修改第三段流量修正值及其系数
#define USB_CMD_SET_COEF_4 0x94 // 修改第四段流量修正值及其系数
/* 状态码定义 */
#define ERR_SUCCESS 0x00 // 操作成功
#define ERR_PARAMETER 0x10 // 参数错误
#define ERR_UNSUPPORT 0x80 // 命令不支持
#define ERR_UNDEFINED 0xFF // 未定义的错误
/* 固件版本信息定义 */
#define THIS_FIRMWARE_VER 0x10 // 固件版本号
#define THIS_APP_SYS_VER 0x10 // 应用系统版本号
#define THIS_APP_SYS_STR "RA50" // 应用系统描述字符串
/* 一般常量定义 */
#define OP_CMD 1 // 命令操作码
#define OP_DATA 0 // 数据操作码
#define DELAY_TIMES 2 // 延时2微秒
#define DELAY_CNT_NUMS DELAY_TIMES*25 // 延时2微秒所需的时钟周期数(对于22.1184MHz晶振,每个微秒包含22.1184个时钟周期)
#define MY_USB_VENDOR_ID 0x4348 // USB设备制造商标识
#define MY_USB_PRODUCT_ID 0x5537 // USB设备产品标识
/* CH372芯片控制引脚定义 */
sbit USB_INT = P0^6; // XBR1.2 = 1(INT0EN = 1), P0MDOUT.6 = 0, INT0作为漏极开路方式输入
sbit USB_A0 = P0^7; // P0MDOUT.7 = 1, 推挽方式, 数字输出
sbit USB_WR = P3^0; // P3MDOUT.0 = 1,推挽方式,作为数字输出
sbit USB_RD = P3^1; // P3MDOUT.1 = 1,推挽方式,作为数字输出
sfr USB_DATA = 0x84; // P74OUT = 0x00,P4口被配置为漏极开路方式,使USB_DATA = 0xFF将其配置为数字输入
/* 引入外部全局变量 */
extern INT16U data gnPressGet; // 测得的气体压力(单位为0.1KPa)
extern INT16U data gnLeakGet; // 测得的气体流量(单位为0.01L/min)
extern INT16U data gnPressSet; // 用户通过触摸屏设定的气体压力(单位为0.1KPa)
extern INT16U data gnPressMax; // 用户通过触摸屏设定的允许最大气体压力(单位为0.1KPa)
extern INT16U data gnPressMin; // 用户通过触摸屏设定的允许最小气体压力(单位为0.1KPa)
extern INT16U data gnLeakMax; // 用户通过触摸屏设定的允许最大气体流量(单位为0.01L/min)
extern INT16U data gnCurrTime; // 代表当前操作正在进行的时间
extern INT16U data gnFillTime; // 用户通过触摸屏设定的充气时间
extern INT16U data gnTestTime; // 用户通过触摸屏设定的测试时间
extern INT16U idata gnLeakAreaMax[6]; // 用户通过触摸屏设定的分段修正流量最大值(单位为0.01L/min)
extern INT16U idata gnLeakAreaCoef[6]; // 用户通过触摸屏设定的分段修正流量系数
/* 延时2微秒,不精确,需要根据硬件实际情况调整 */
void Delay2us( )
{
INT8U i;
i = (INT8U)DELAY_CNT_NUMS;
while (--i);
}
/* 与CH372/CH375有关的基本I/O操作 */
/* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 */
void CH375_WR_CMD_PORT(INT8U cmd)
{
USB_WR = 1;
USB_RD = 1;
Delay2us();
USB_A0 = OP_CMD; // 准备写命令
USB_DATA = cmd; // 准备命令数据
USB_WR = 0; // 开始写命令
Delay2us();
USB_WR = 1; // 结束写命令(USB_WR信号的有效时间不能超过10us)
}
/* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 */
void CH375_WR_DAT_PORT(INT8U dat)
{
USB_WR = 1;
USB_RD = 1;
Delay2us();
USB_A0 = OP_DATA; // 准备写数据
USB_DATA = dat; // 准备数据
USB_WR = 0; // 开始写数据
Delay2us();
USB_WR = 1; // 结束写命令(USB_WR信号的有效时间不能超过10us)
}
/* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
INT8U CH375_RD_DAT_PORT(void)
{
INT8U nData;
USB_WR = 1;
USB_RD = 1;
Delay2us();
USB_DATA = 0xFF; // 将USB_DATA(P4口)配置为数字输入
USB_A0 = OP_DATA; // 准备读数据
USB_RD = 0; // 开始读数据
Delay2us();
nData = USB_DATA; // 读取数据
USB_RD = 1; // 结束读命令(USB_RD信号的有效时间不能超过10us)
return nData; // 返回读取的数据
}
/* CH375初始化子程序 */
void CH375_Init(void)
{
INT8U i;
/* 如果设置使用自定义的ID,那么计算机端驱动程序INF安装文件中的"USB\VID_4348&PID_5537"需要进行类似修改 */
CH375_WR_CMD_PORT(CMD_SET_USB_ID); // 设置外部自定义的USB设备VID和PID,可选操作
CH375_WR_DAT_PORT((INT8U)MY_USB_VENDOR_ID); // 写入厂商ID的低字节
CH375_WR_DAT_PORT((INT8U)(MY_USB_VENDOR_ID>>8)); // 写入厂商ID的高字节
CH375_WR_DAT_PORT((INT8U)MY_USB_PRODUCT_ID); // 写入产品ID的低字节
CH375_WR_DAT_PORT((INT8U)(MY_USB_PRODUCT_ID>>8)); // 写入产品ID的高字节
/* 设置USB工作模式(内置固件的USB设备方式), 必要操作 */
CH375_WR_CMD_PORT(CMD_SET_USB_MODE);
CH375_WR_DAT_PORT(2);
/* 等待操作成功,通常需要等待10uS-20uS */
for (i=100; i!=0; i--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -