⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 HID类程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
基于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 + -