📄 main.c
字号:
/*
基于18F4550的HID程序设计
此程序只完成从主机发送2字节数据,然后设备把数据原封不动返回主机
编译器:MCC18
版本:MPLAB-C18-v3_02
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Zhongxin An 2007.7.3 HID
*/
#include <p18cxxx.h>
#include "typedefint.h"
#include "USb data.h"
#define USB_sense PORTAbits.RA1 //USB 上电检测端口
#define tris_usb_bus_sense TRISAbits.TRISA1
/**************************
* 函数定义
***************************/
#pragma udata
//---------主函数定义区---------
void InitializeSystem(void);//系统初始化
void USBTasks(void); //USB任务
void ProcessIO(void); //用户函数
void mInitializeUSBDriver(void);//初始化USB设备
void UserInit(void); //用户初始化程序
void ClearArray(byte* startAdr,byte count); //地址清0函数
void mDisableEP1to15(void); //端点清0函数
//------------------------------
//--------USB控制传输函数区--------
void USBPrepareForNextSetupTrf(void); // 为下次USB控制传输SETUP做准备
void USBCtrlEPService(void); // USB 控制端点服务程序,在事务中断中调用
void USBCtrlTrfSetupHandler(void); // USB控制传输设置处理函数
void USBCtrlTrfOutHandler(void); // USB控制输出函数(数据主机-设备)
void USBCtrlTrfInHandler(void); // USB控制输入数据(数据设备-主机)
void USBCtrlEPServiceComplete(void); // USB控制传输端点服务完成
void USBCtrlTrfTxService(void); // USB控制传输数据设备到主机
void USBCtrlTrfRxService(void); // USB控制数据输出数据主机到设备
//---------------------------------
//--------USB 协议函数区-----------
void USBCheckStdRequest(void); // 检测USB的标准请求
void USBStdGetDscHandler(void); // USB获得标准描述符处理函数
void USBStdSetCfgHandler(void); // USB指示设备使用所选择的配置处理
void USBStdGetStatusHandler(void); // USB主机获得状态处理函数
void USBStdFeatureReqHandler(void);// 主机请求启用特征值处理函数
void mUSBCheckAdrPendingState(void); // USB检测地址状态是否已经配置
//---------------------------------
//-----------HID 函数区-------------
void HIDInitEP(void); // HID端点设置函数
void USBCheckHIDRequest(void); // USB HID请求检测
void HIDGetReportHandler(void); // 主机获得报表处理函数
void HIDSetReportHandler(void); // 设备获得报表处理函数
byte HIDRxReport(char *buffer, byte len); // HID取出接收数据长度函数
void HIDTxReport(char *buffer, byte len); // HID发送到主机数据
//----------------------------------
//-----------USB用户专用区----------
void GetInputReport0(void); // 主机获得数据
void GetFeatureReport0(void); // 主机获得特征
void HandleControlOutReport(void); // HID发送报表(主机发送)
void ReportLoopback(void); // b报表查询函数
//----------------------------------
//-------USB 总线以及设备服务函数-------
void USBCheckBusStatus(void); // USB总线检测函数
void USBDriverService(void); // USB设备服务程序
//--------------------------------------
extern void _startup (void); // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800 //复位
void _reset (void)
{
_asm goto _startup _endasm
}
#pragma code
#pragma code
/***************************
* 主函数
****************************/
void main()
{
InitializeSystem(); //系统初始化函数
while(1)
{
USBTasks(); //USB 任务函数
ProcessIO(); //
}
}//end main()
//------------------------------------------------------------主函数子函数区
/***************************
* 系统初始化函数
****************************/
void InitializeSystem()
{
WDTCONbits.SWDTEN=0; //禁止看门狗
ADCON1=0x0f; //把模拟端口全部设置为数字端口
HLVDCONbits.HLVDEN=0; //禁止低压检测
INTCON=0; //中断禁止
CMCON=0x07; //禁止比较器
#if defined(USE_USB_BUS_SENSE_IO)
tris_usb_bus_sense = 1; //此端口正常状态为低,如果为高则接入
#endif
mInitializeUSBDriver(); //初始化USB设备
UserInit(); //用户初始化
}//end InitializeSystem()
/***************************
* 用户初始化
****************************/
void UserInit()
{
// TRISB=0; //设置为输出引脚,指示状态端口
// PORTB=0;
LATD &= 0xF0; TRISD &= 0xF0; //LED指示灯
} //end UserInit()
/***************************
* USB 设备初始化函数
****************************/
void mInitializeUSBDriver()
{
UCFG = UCFG_VAL; //USB配置寄存器值,=0x14使能片上上拉,片上收发,全速,禁止乒乓缓冲
usb_device_state = DETACHED_STATE; //USB处于分离状态
usb_stat._byte = 0x00; //USB状态清0
usb_active_cfg = 0x00; //USB现行配置清0
}//end mInitializeUSBDriver()
/****************************
* USB任务函数
*****************************/
void USBTasks()
{
USBCheckBusStatus(); //USB检测总线状态函数
if(UCFGbits.UTEYE!=1) //如果禁止眼图测试
{
USBDriverService(); //USB设备服务程序
}
}//end USBTasks()
/*****************************
* 用户函数
*****************************/
void ProcessIO()
{
// 如果USB没有进入配置状态或者USB处于挂起状态返回
if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;
ReportLoopback(); //查询报表
}//end ProcessIO()
//----------------------------------------------------------END 主函数子函数区
//-----------------------------------------------------------2级main函数程序区
/*************************
* USB检测总线状态函数
**************************/
void USBCheckBusStatus()
{
if(USB_sense==USB_BUS_ATTACHED) //如果USB设备上电
{
if(UCONbits.USBEN == 0) //如果USB现在处于禁止状态,使能
{
UCON = 0;
UIE = 0; // 清除所有USB中断
UCONbits.USBEN = 1; // 使能USB模块
usb_device_state = ATTACHED_STATE; // USB进入上电状态
}//end if
}
else
{
if(UCONbits.USBEN == 1) // 如果USB处于使能状态,禁止
{
UCON = 0; // 禁止USB模块
UIE = 0; // 清所有USB中断
usb_device_state = DETACHED_STATE; // USB设备处于断开状态
}//end if
}//end if(USB_sense==USB_BUS_ATTACHED)
if(usb_device_state == ATTACHED_STATE) //如果USB处于上电状态
{
if(!UCONbits.SE0) //未检测到单端0
{
UIR = 0; // 清除所有USB中断标志
UIE = 0; // 复位所有USB中断
UIEbits.URSTIE = 1; // 允许复位中断
UIEbits.IDLEIE = 1; // 允许空闲检测中断
usb_device_state = POWERED_STATE;//POWERED_STATE=2,USB总线有效状态
}//end if
}//end if(USB_sense == USB_BUS_ATTACHED)
}//end USBCheckBusStatus()
/*************************
* USB设备服务函数
*************************/
void USBDriverService()
{
if(usb_device_state == DETACHED_STATE) return; //如果状态为0返回,此时USB并没有上电
//任务A
//总线活动检测中断任务,这个中断是在挂起后才开启
if(UIRbits.ACTVIF && UIEbits.ACTVIE) //USB从挂起中唤醒,总线活动中断
{
UCONbits.SUSPND = 0; //USB模块退出挂起状态,进入正常工作状态
UIEbits.ACTVIE = 0; //清标志并禁止总线活动中断
UIRbits.ACTVIF = 0;
}//end if
if(UCONbits.SUSPND==1) return; //如果总线处于挂起状态则返回,不进行处理
//任务B:
//USB总线复位中断输入
if(UIRbits.URSTIF && UIEbits.URSTIE) //确认复位中断输入
{
UEIR = 0; // 清除所有的错误中断标志
UIR = 0; // 清除USB中断标志
UEIE = 0b10011111; // 启动所有USB错误中断
UIE = 0b01111011; // 启动除活动检测中断以外的所有USB中断
UADDR = 0x00; // 复位到默认地址
mDisableEP1to15(); // 复位除了EP0的其他端点
UEP0 = EP_CTRL|HSHK_EN; //端点0使能为控制端口
while(UIRbits.TRNIF == 1) // 清除一切未决传输
{
UIRbits.TRNIF = 0;
}
UCONbits.PKTDIS = 0; // 确保SIE令牌和包处理使能
USBPrepareForNextSetupTrf();//USB为下一次控制传输的SETUP做好准备
usb_stat.RemoteWakeup = 0; // 清除默认状态标志
usb_active_cfg = 0; // Clear active configuration
usb_device_state = DEFAULT_STATE; //=3 进入默认状态
}//end if
//任务C 完成其他USB中断的处理
if(UIRbits.IDLEIF && UIEbits.IDLEIE) // 如果产生总线空闲中断,则USB需要挂起
{
UIEbits.ACTVIE = 1; // 使能总线活动中断
UIRbits.IDLEIF = 0; // 清除总线空闲中断标志
UCONbits.SUSPND = 1;// 挂起USB
//下面也可以加中断源,后休眠单片机,此处没有添加,唤醒后可通过远程唤醒进行通信
/*
// 因为应用程序没有能够唤醒的,所以暂时不加,所以远程唤醒没有
*/
}//end if
if(UIRbits.SOFIF && UIEbits.SOFIE) //如果产生令牌中断
{
UIRbits.SOFIF = 0; //清标志位
}//end if
if(UIRbits.STALLIF && UIEbits.STALLIE) //如果产生握手中断
{
if(UEP0bits.EPSTALL == 1)// 如果端点停止,因为一般产生握手中断后,标志着这次传输的结束
{ // 端点会自动禁止
USBPrepareForNextSetupTrf(); // 准备下一次SETUP传输
UEP0bits.EPSTALL = 0; // 使能端点0
}//end if
UIRbits.STALLIF = 0; // 握手中断信号清0
}//end if
if(UIRbits.UERRIF && UIEbits.UERRIE) // 如果产生USB错误中断
{
UIRbits.UERRIF=0;
}//end if
if(usb_device_state < DEFAULT_STATE) return; // 如果没有进入默认状态退出
// 这是在产生一次复位后才能进入默认态
if(UIRbits.TRNIF && UIEbits.TRNIE) // 如果产生事务中断
{
USBCtrlEPService(); // USB控制端点服务函数(默认是EP0)
UIRbits.TRNIF = 0; // 标志清0
}//end if
}//end USBDriverService()
/**********************
* 复位端点
***********************/
void mDisableEP1to15()
{
ClearArray((byte*)&UEP1,15);
}//end mDisableEP1to15()
/***********************
* 地址数据清0 函数
************************/
void ClearArray(byte* startAdr,byte count)
{
*startAdr;
while(count)
{
_asm
clrf POSTINC0,0 //见18汇编,执行完后,地址自动加1,而UEP地址是连续的
_endasm
count--;
}//end while
}//end ClearArray
//------------------------------------------------------end 2级main 子函数定义
//-------------------------------------------------------控制传输函数区
/**************************************
* USB 为下一次的控制传输的SETUP做好准备
***************************************/
void USBPrepareForNextSetupTrf()
{
ctrl_trf_state = WAIT_SETUP; // See usbctrltrf.h
ep0Bo.Cnt = EP0_BUFF_SIZE; //定义数据去大小,8个字节
ep0Bo.ADR = (byte*)&SetupPkt; //取数据区首地址
ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; // EP0 OUT 缓冲描述符状态设置
ep0Bi.Stat._byte = _UCPU; // EP0 IN 缓冲区初始化,缓冲区归CPU,
// 如果归SIE则将启动数据发送
}//end USBPrepareForNextSetupTrf()
/****************************
* USB 控制端点服务程序
****************************/
void USBCtrlEPService()
{
if(USTAT == EP00_OUT) //如果上一次是OUT或SETUP令牌,并且是端点0
{
if(ep0Bo.Stat.PID == SETUP_TOKEN) // EP0 SETUP,如果是配置设置
USBCtrlTrfSetupHandler(); // USB控制传输设置处理函数
else
USBCtrlTrfOutHandler(); // OUT事务,从主机接收数据
}
else if(USTAT == EP00_IN) // EP0 IN,输入事务
USBCtrlTrfInHandler(); // IN事务传送数据到主机
}//end USBCtrlEPService()
/*******************************
* USB控制传输设置处理函数
********************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -