www.pudn.com > D12Driver.rar > D12Driver.c
/****************************************Copyright (c)***************************** * 广州周立功单片机发展有限公司 * 研 究 所 * 产品一部 * * http://www.zlgmcu.com * * 文 件 名: D12Driver.c * 最后修改日期: 2006年03月27日 * 描 述: USB驱动程序软件包: PDIUSBD12 设备端驱动程序 驱动层 * 版 本: ************************************************************************************/ #include#include"intrins.h" #include"GENERAL.h" #include"AGREEMENT.h" #include"D12DRIVER.h" #include"RS485Driver.h" INT8U idata GenEpBuf[EP1_PACKET_SIZE]; // 端点1接收缓冲区 INT8U idata EpBuf[EP2_PACKET_SIZE]; // 端点2接收缓冲区 extern EPPFLAGS idata bEPPflags; // 引用USB事件标志变量 extern CONTROL_XFER idata ControlData; // 引用控制传输结构变量 extern INT8U idata Len_ep1Buffer; // 引用端点1接收数据长度 extern INT8U idata Len_ep2Buffer; // 引用端点2接收数据长度 //-------------------------------------------------------- // 函数名称: void Init_D12Port(void) // 功能描述: 初始化D12与MCU的连接端口 //-------------------------------------------------------- void Init_D12Port(void) { MCU_D12CS = 1; // 释放D12 MCU_D12CS = 0; // 选择D12 _nop_(); } //-------------------------------------------------------- // 函数名称: void Rst_D12(void) // 功能描述: 复位D12 //-------------------------------------------------------- void Rst_D12(void) { INT16U i; MCU_D12RST = 0; // D12的 RESET引脚置0 for(i = 0; i < 0x100; i++); // 软件延时 { MCU_D12RST = 1; // D12的 RESET引脚置1 } MCU_D12SUSPD = 0; // D12的 SUSPEND引脚置0 } //-------------------------------------------------------- // 函数名称: outportb() // 功能描述: 向D12写入数据 // 输 入: INT16U Addr: 命令地址或数据地址 // INT8U Data: 命令字节 // 输 出: 无 //-------------------------------------------------------- void outportb(INT8U Addr, INT8U Data) { MCU_D12RD = 1; MCU_D12WR = 0; if(Addr) { MCU_D12A0 = 1; P0 = Data; } else { MCU_D12A0 = 0; P0 = Data; } MCU_D12WR = 1; } //-------------------------------------------------------- // 函数名称: inportd() // 功能描述: 读入数据 // 输 入: INT16U Addr: 数据地址 // 输 出: 读到的数据 //-------------------------------------------------------- INT8U inportb(void) { INT8U DAT_TEMP; MCU_D12WR = 1; MCU_D12A0 = 0; P0 = 0xFF; MCU_D12RD = 0; _nop_(); DAT_TEMP = P0; _nop_(); MCU_D12RD = 1; return (DAT_TEMP); } //-------------------------------------------------------- // 函数名称: connect_USB() // 功能描述: 连接USB总线 //-------------------------------------------------------- void connect_USB(void) //SoftConnect 连接上,并设置为无LazyClock,模式为非同步模式 { D12_SetDMA(0x00); D12_SetMode(D12_NOLAZYCLOCK|D12_SOFTCONNECT, D12_SETTOONE | D12_CLOCK_12M); } //-------------------------------------------------------- // 函数名称: disconnect_USB() // 功能描述: 断开USB总线 //-------------------------------------------------------- void disconnect_USB(void) //SoftConnect 断开 { D12_SetMode(D12_NOLAZYCLOCK, D12_SETTOONE | D12_CLOCK_12M); } //-------------------------------------------------------- // 函数名称: reconnect_USB() // 功能描述: 重新连接USB总线 //-------------------------------------------------------- void reconnect_USB(void) { INT16U clk_cnt; disconnect_USB(); // 断开芯片与USB总线连接 for (clk_cnt = 0;clk_cnt<= 0x9000;clk_cnt++); // 延时处理 { connect_USB(); // 连接到USB总线 } } //-------------------------------------------------------- // 函数名称: D12_ReadChipID() // 功能描述: 读取芯片ID // 输 入: 无 // 输 出: 芯片的ID号 //-------------------------------------------------------- INT16U D12_ReadChipID(void) { INT16U i,j; if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0xFD); // 发送读PDIUSBD12芯片ID号命令 _nop_(); i=inportb(); // 读取ID号低字节 _nop_(); j=inportb(); // 读取ID号高位字节 i += (j<<8); // 组成16位的PDIUSBD12芯片ID号 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } return i; } //-------------------------------------------------------- // 函数名称: Init_D12() // 功能描述: 设置D12与硬件的连接, 初始化D12, 复位D12 // 输 入: 无 // 输 出: 0: 初始化成功 1: 初始化失败 //-------------------------------------------------------- INT8U Init_D12(void) { bEPPflags.value = 0; // 初始化USB事件标志变量 Init_D12Port(); // 初始化PDIUSBD12与51单片机连接的端口 Rst_D12(); // 复位PDIUSBD12 reconnect_USB(); // 重新连接USB if (D12_ReadChipID() != 0x1012) // 读取芯片ID号,如果不为1012H { return 1; // 则复位失败 } return 0; // 初始化成功 } //-------------------------------------------------------- // 函数名称: d12_busreset() // 功能描述: USB总线复位处理函数 // 输 入: 无 // 输 出: 无 //-------------------------------------------------------- void d12_busreset(void) { //在此添加总线复位处理代码 } //-------------------------------------------------------- // 函数名称: dma_eot() // 功能描述: DMA结束处理函数 // 输 入: 无 // 输 出: 无 //-------------------------------------------------------- void dma_eot(void) { //在此添加DMA结束处理代码 } //-------------------------------------------------------- // 函数名称: d12_suspend() // 功能描述: 总线挂起改变处理函数 // 输 入: 无 // 输 出: 无 //-------------------------------------------------------- void d12_suspend(void) { //在此添加总线挂起改变代码 } //-------------------------------------------------------- // 函数名称: usbserve() // 功能描述: USB事件处理函数 // 输 入: 无 // 输 出: 无 //-------------------------------------------------------- void usbserve(void) { if(bEPPflags.bits.setup_packet) { // Setup包处理 DISABLE(); bEPPflags.bits.setup_packet = 0; control_handler(); // 调用请求处理子程序 ENABLE(); } if (bEPPflags.bits.bus_reset) { // USB总线复位处理 DISABLE(); bEPPflags.bits.bus_reset = 0; ENABLE(); d12_busreset(); //有待处理 } if (bEPPflags.bits.suspend) { // D12挂起改变处理 DISABLE(); bEPPflags.bits.suspend= 0; ENABLE(); d12_suspend(); //有待处理 } //在此添加其它usb事件处理代码 } //-------------------------------------------------------- // 函数名称: D12_SetAddressEnable() // 功能描述: 设置地址/使能 // 输 入: INT8U bAddress: 地址 // INT8U bEnable : 0 --- 禁止 // 1 --- 使能 // 输 出: 无 //-------------------------------------------------------- void D12_SetAddressEnable(INT8U bAddress, INT8U bEnable) { if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0xD0); // 输出设置地址/使能指令 if(bEnable) { bAddress |= 0x80; // bit7置1,使能 } outportb(D12_DATA, bAddress); // 输出设置值 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } } //-------------------------------------------------------- // 函数名称: D12_SetEndpointEnable() // 功能描述: 设置端点使能 // 输 入: INT8U bEnable : 0 --- 禁止 // 1 --- 允许 // 输 出: 无 //-------------------------------------------------------- void D12_SetEndpointEnable(INT8U bEnable) { if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0xD8); // 输出设置端点使能指令 if(bEnable) { outportb(D12_DATA, 1); // 设置端点允许 } else { outportb(D12_DATA, 0); // 设置端点禁止 } if(bEPPflags.bits.in_isr == 0) { ENABLE(); } } //-------------------------------------------------------- // 函数名称: void D12_SetMode() // 功能描述: 模式设置 // 输 入: INT8U bConfig: 配置字节信息 // INT8U bClkDiv: 分频系数 // 输 出: 无 //-------------------------------------------------------- void D12_SetMode(INT8U bConfig,INT8U bClkDiv) { if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0xF3); // 输出设置模式指令 outportb(D12_DATA, bConfig); // 输出配置字节信息 outportb(D12_DATA, bClkDiv); // 输出时钟分频因数字节 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } } //-------------------------------------------------------- // 函数名称: void D12_SetDMA() // 功能描述: 设置DMA工作方式设置 // 输 入: INT8U bMode: 设置值 // 输 出: 无 //-------------------------------------------------------- void D12_SetDMA(INT8U bMode) { if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0xFB); // 设置DMA工作方命令 outportb(D12_DATA, bMode); // 输出设置值 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } } //-------------------------------------------------------- // 函数名称: D12_ReadInterruptRegister() // 功能描述: 读取中断寄存器值 // 输 入: 无 // 输 出: 中断寄存器值 //-------------------------------------------------------- INT16U D12_ReadInterruptRegister(void) { INT8U b1; INT16U j; outportb(D12_COMMAND, 0xF4); // 读取中断寄存器命令 b1 = inportb(); // 读取低8位字节 j = inportb(); // 读取高8位字节 j <<= 8; j += b1; // 组合为16位 return j; } //-------------------------------------------------------- // 函数名称: D12_SelectEndpoint() // 功能描述: 端点选择,将内部指针初始化到选择的缓冲区起始位置 // 输 入: INT8U bEndp: 端点索引号,取值0 ~ 5 // 输 出: 读出的字节 //-------------------------------------------------------- INT8U D12_SelectEndpoint(INT8U bEndp) { INT8U c; if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, bEndp); // 端点选择 c = inportb(); // 读出一个字节 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } return c; } //-------------------------------------------------------- // 函数名称: D12_ReadEndpointStatus() // 功能描述: 读取端点状态 // 输 入: INT8U bEndp: 端点索引号,取值0 ~ 5 // 输 出: 端点状态 //-------------------------------------------------------- INT8U D12_ReadEndpointStatus(INT8U bEndp) { INT8U c; if(bEPPflags.bits.in_isr == 0) DISABLE(); outportb(D12_COMMAND, 0x80 + bEndp); // 读取端点状态命令 c = inportb(); // 读取端点状态 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } return c; } //-------------------------------------------------------- // 函数名称: D12_ReadLastTransactionStatus() // 功能描述: 读取最后处理状态寄存器 // 输 入: INT8U bEndp: 端点索引号,取值0 ~ 5 // 输 出: 端点最后处理的状态 //-------------------------------------------------------- INT8U D12_ReadLastTransactionStatus(INT8U bEndp) { outportb(D12_COMMAND, 0x40 + bEndp); // 输出读取最后处理状态寄存器命令 return inportb(); // 读取状态 } //-------------------------------------------------------- // 函数名称: D12_SetEndpointStatus() // 功能描述: 设置端点状态 // 输 入: INT8U bEndp: 端点索引号,取值0 ~ 5 // INT8U bStalled: 状态值 // 输 出: 端点状态 //-------------------------------------------------------- void D12_SetEndpointStatus(INT8U bEndp,INT8U bStalled) { if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0x40 + bEndp); // 发送设置端点状态命令 outportb(D12_DATA, bStalled); // 设置端点状态 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } } //-------------------------------------------------------- // 函数名称: D12_SendResume() // 功能描述: 传输恢复 //-------------------------------------------------------- /*void D12_SendResume(void) { outportb(D12_COMMAND, 0xF6); // 设置发送恢复 } */ /************************************************************ ** 函数名称: D12_ReadCurrentFrameNumber() ** 功能描述: 读取当前帧号 ** 输 入: 无 ** 输 出: 当前帧号 ************************************************************/ /*INT16U D12_ReadCurrentFrameNumber(void) { INT16U i,j; if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, 0xF5); //发送读取当前帧数目命令 i= inportb(); //读取帧数目的低8位 j = inportb(); //读取帧数目的高8位 i += (j<<8); if(bEPPflags.bits.in_isr == 0) { ENABLE(); } return i; //返目当前帧数目 } */ //-------------------------------------------------------- // 函数名称: D12_ReadEndpoint() // 功能描述: 读取端点数据 // 输 入: INT8U endp: 端点索引号,取值 0 ~ 5 // INT8U len: 要读取的数据长度 // INT8U * buf: 接收数据指针 // 输 出: 实际读得的字节数 //-------------------------------------------------------- INT8U D12_ReadEndpoint(INT8U endp,INT8U len,INT8U * buf) { INT8U i, j; if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, endp); // 发送选择端点命令 if((inportb() & D12_FULLEMPTY) == 0) { // 如果缓冲区为空 if(bEPPflags.bits.in_isr == 0) { ENABLE(); } return 0; // 则返回读到0字节 } outportb(D12_COMMAND, 0xF0); // 发送读缓冲区命令 j = inportb(); // 读取保留字节 j = inportb(); // 读取数据字节的数目/长度 if(j > len) // 如果大于要求读的字节数目 { j = len; // 则只读取要求的字节长度 } for(i=0; i = 4) { outportb(D12_COMMAND,0xF2); // 清空第2个缓冲区 } if(bEPPflags.bits.in_isr == 0) { ENABLE(); } return j; // 返回读到的字节数 } //-------------------------------------------------------- // 函数名称: D12_WriteEndpoint() // 功能描述: 把数据写入端点 // 输 入: INT8U endp: 端点索引号,取值 0 ~ 5 // INT8U len: 要写入的数据长度 // INT8U * buf: 发送数据指针 // 输 出: 实际写入的字节数 //-------------------------------------------------------- INT8U D12_WriteEndpoint(INT8U endp, INT8U len,INT8U * buf) { INT8U i; if(bEPPflags.bits.in_isr == 0) { DISABLE(); } outportb(D12_COMMAND, endp); // 发送选择端点命令 i = inportb(); // 可选地读取一个字节 outportb(D12_COMMAND, 0xF0); //发送写缓冲区命令 outportb(D12_DATA, 0); //写入一个保留字节 outportb(D12_DATA, len); //写入即将写入的字节数目 for(i=0; i MAX_CONTROLDATA_SIZE) { // 数据长度出错 bEPPflags.bits.control_state = USB_IDLE; // 设置为等待状态 D12_SetEndpointStatus(0, 1); // 停止控制端点0 D12_SetEndpointStatus(1, 1); // 停止控制端点1 } else { bEPPflags.bits.control_state = USB_RECEIVE; // 设置为接收状态 } } } } /***** 下面为控制写入的数据阶段 ***************/ else if(bEPPflags.bits.control_state == USB_RECEIVE) { // 如果为接收状态 i = D12_ReadEndpoint(0, EP0_PACKET_SIZE, ControlData.dataBuffer + ControlData.wCount); // 从端点0接收数据 ControlData.wCount += i; // 统计已接收的字节数 if( i != EP0_PACKET_SIZE || ControlData.wCount >= ControlData.wLength) { // 数据接收完毕 bEPPflags.bits.setup_packet = 1; // 通知control_handler()处理Setup包 bEPPflags.bits.control_state = USB_IDLE; // 设置为等待状态 } } else { bEPPflags.bits.control_state = USB_IDLE; // 设置等待状态 } } //-------------------------------------------------------- // 函数名称: void ep0_txdone(void) // 功能描述: 通过端点索引 1 发送数据 //-------------------------------------------------------- void ep0_txdone(void) { INT16 i = ControlData.wLength - ControlData.wCount; // 计算未发送的字节数 D12_ReadLastTransactionStatus(1); // 清除中断寄存器标志位 if (bEPPflags.bits.control_state != USB_TRANSMIT) { // 非发送状态 single_transmit(0, 0); return; // 返回 } if( i >= EP0_PACKET_SIZE) { // 未发送字节数大于16,发送16个字节 D12_WriteEndpoint(1, EP0_PACKET_SIZE, ControlData.pData + ControlData.wCount); ControlData.wCount += EP0_PACKET_SIZE; bEPPflags.bits.control_state = USB_TRANSMIT; } else if( i != 0) { // 发送所有未发送的字节 D12_WriteEndpoint(1, i, ControlData.pData + ControlData.wCount); ControlData.wCount += i; bEPPflags.bits.control_state = USB_IDLE; // 置状态为等待状态 } else if (i == 0) { D12_WriteEndpoint(1, 0, 0); // 发送完毕,发0个字节 bEPPflags.bits.control_state = USB_IDLE; } } //-------------------------------------------------------- // 函数名称: ep1_rxdone() // 功能描述: 通过端点索引 2 接收数据 // 输 入: 无 // 输 出: 接收数据长度 //-------------------------------------------------------- INT8U ep1_rxdone(void) { INT8U len = 0; D12_ReadLastTransactionStatus(2); // 清中断标志位 len = D12_ReadEndpoint(2,EP1_PACKET_SIZE,GenEpBuf); // 读取数据 return len; } //-------------------------------------------------------- // 函数名称: ep2_rxdone() // 功能描述: 通过端点索引 4 接收数据 // 输 入: 无 // 输 出: 接收数据长度 //-------------------------------------------------------- INT8U ep2_rxdone(void) { INT8U len = 0; D12_ReadLastTransactionStatus(4); // 清中断标志位 len = D12_ReadEndpoint(4,EP2_PACKET_SIZE,EpBuf); // 读取缓冲区中的数据 return len; } //-------------------------------------------------------- // 函数名称: void Usb_Exception(void) // 功能描述: D12中断服务程序 //-------------------------------------------------------- void USB_INT1() interrupt 2 { INT16U i_st; DISABLE(); // 进入D12中断服务程序时关中断 bEPPflags.bits.in_isr = 1; i_st = D12_ReadInterruptRegister(); // 读取PDIUSBD12中断寄存器值 if(i_st != 0) { if(i_st & D12_INT_BUSRESET) { bEPPflags.bits.bus_reset = 1; // USB总线复位标志 } if(i_st & D12_INT_EOT) { dma_eot(); // DMA传输技术处理 } if(i_st & D12_INT_SUSPENDCHANGE) { bEPPflags.bits.suspend = 1; // 挂起改变标志置1 } if(i_st & D12_INT_ENDP0IN) { ep0_txdone(); // 控制端点发送数据处理 } if(i_st & D12_INT_ENDP0OUT) { ep0_rxdone(); // 控制端点接收数据处理 } if(i_st & D12_INT_ENDP1IN) { // 端点 1发送数据处理 D12_ReadLastTransactionStatus(3); } if(i_st & D12_INT_ENDP1OUT) { Len_ep1Buffer = ep1_rxdone(); // 端点 1接收数据处理 } if((i_st & D12_INT_ENDP2IN)) { D12_ReadLastTransactionStatus(5); // 端点 2发送数据处理 } if(i_st & D12_INT_ENDP2OUT) { Len_ep2Buffer = ep2_rxdone(); // 端点 2 接收数据处理 } } bEPPflags.bits.in_isr = 0; ENABLE(); // 退出D12中断服务程序时开中断 } //-------------------------------------------------------- // 函数名称: Get_D12_FirmwareVer() // 功能描述: 重新连接USB总线 // 输 入: 无 // 输 出: 16bit整数,如0x0500表示D12固件软件版本号为5.00 //-------------------------------------------------------- /*INT16U Get_D12_FirmwareVer(void) { return 0x0500; //D12固件软件版本号为5.00 } */