- 打卡等级:初来乍到
- 打卡总天数:2
- 最近打卡:2026-02-27 11:37:25
已绑定手机
新手上路
- 积分
- 11
|
// USB命令定义,VC的stdafx.h中同样定义
#define CMD_Usb_CDC_OK 0xa5
#define CMD_Usb_CDC_NG 0xa6
#define CMD_Usb_CDC_Check 0x1a //检测USB-CDC串口通信,返回1个字节0x1a给串口
#define CMD_Send_Data 0x2a //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_Send_Strobe 0x3a //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_Pass_Sound 0x8a //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_Fail_Sound 0x9a //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_Alarm_Sound 0xaa //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_Key_Sound 0xba //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_Pin_Sound 0xca //返回CMD_Usb_CDC_OK或CMD_Usb_CDC_OK一个字节
#define CMD_QUEUE_SIZE 16 // 队列深度,根据实际需求调整
#define CMD_MAX_LEN 20 // 最大命令长度
typedef struct
{
u8 len;
u8 dataBuf[CMD_MAX_LEN];
} CmdItem;
CmdItem cmdQueue[CMD_QUEUE_SIZE];
volatile u8 cmdQueueHead = 0; // 生产者索引(中断中修改)
volatile u8 cmdQueueTail = 0; // 消费者索引(主循环中修改)
void usb_callback()
{
u8 i;
u8 next = (cmdQueueHead + 1) % CMD_QUEUE_SIZE;
if (OutNumber == 0 || OutNumber > CMD_MAX_LEN) return;
// 队列满时覆盖最旧的一条(可根据需求丢弃或等待)
if (next == cmdQueueTail) {
cmdQueueTail = (cmdQueueTail + 1) % CMD_QUEUE_SIZE; // 丢弃最旧命令
}
cmdQueue[cmdQueueHead].len = OutNumber;
for (i = 0; i < OutNumber; i++)
{
cmdQueue[cmdQueueHead].dataBuf[i] = UsbOutBuffer[i];
}
cmdQueueHead = next;
}
void ProcessUsbCommand(u8* dataBuf, u8 len)
{//UsbOutBuffer为接收到数据缓冲区,OutNumber为接收到的数据字节数
u8 return_buf[8];
if (len == 0) return;
if(OutNumber == 0) return;
switch(dataBuf[0])
{
case CMD_Usb_CDC_Check: //0x1a:检测USB-CDC串口通信,返回0x1a给串口
return_buf[0]=CMD_Usb_CDC_Check;
USB_SendData(return_buf, 1); //发送数据缓冲区,字节长度
break;
case CMD_Send_Data:
Send_Data(dataBuf, len);
break;
case CMD_Send_Strobe:
Send_Strobe(dataBuf, len);
break;
case CMD_Pass_Sound:
Song(3,2); //0,1 is Key_Sound; 1,1 is Pin_Sound; 2,1 is Fail_Sound; 3,2 is Pass_Sound
//Pass_Sound();
return_buf[0] = CMD_Usb_CDC_OK;
USB_SendData(return_buf, 1);
break;
case CMD_Fail_Sound:
Song(2,1); //0,1 is Key_Sound; 1,1 is Pin_Sound; 2,1 is Fail_Sound; 3,2 is Pass_Sound
//Fail_Sound();
return_buf[0] = CMD_Usb_CDC_OK;
USB_SendData(return_buf, 1);
break;
case CMD_Alarm_Sound:
Song(2,1); //0,1 is Key_Sound; 1,1 is Pin_Sound; 2,1 is Fail_Sound; 3,2 is Pass_Sound
//Fail_Sound();
return_buf[0] = CMD_Usb_CDC_OK;
USB_SendData(return_buf, 1);
break;
case CMD_Key_Sound:
Song(0,1); //0,1 is Key_Sound; 1,1 is Pin_Sound; 2,1 is Fail_Sound; 3,2 is Pass_Sound
//Key_Sound();
return_buf[0] = CMD_Usb_CDC_OK;
USB_SendData(return_buf, 1);
break;
case CMD_Pin_Sound:
Song(1,1); //0,1 is Key_Sound; 1,1 is Pin_Sound; 2,1 is Fail_Sound; 3,2 is Pass_Sound
//Pin_Sound();
return_buf[0] = CMD_Usb_CDC_OK;
USB_SendData(return_buf, 1);
break;
case CMD_Write_Fixture:
Write_Fixture(dataBuf, len);
break;
case CMD_Write_Mark:
Write_Mark(dataBuf, len);
break;
case CMD_Rel_Fixture:
DOWN=1;//DOWN OFF
_nop_();
UP=0;//UP ON
_nop_();
break;
case CMD_Read_Fixture:
Read_Fixture(len);
break;
case CMD_Read_Adc:
Read_Adc(dataBuf, len);
break;
case CMD_Read_Comp:
Read_Comp(dataBuf, len);
break;
default:
break;
}
}
void main()
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,
//赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,
//赋值为 0 表示用最快速度访问,
//不增加额外的等待时
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
P3M0 = 0x80; P3M1 = 0x00; //设置 P3 口为准双向口模式,P3.7强上拉,P3M1:P3M0=0:0为准双向口/弱上拉, P3M1:P3M0=0:1为强推挽/强上拉
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x01; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
usb_init(); //调用 USB 初始化函数,不需要立即判断电脑已正确识别到 USB 从设备
/* USB 型单片机从设备,如需要主动向电脑发送数据,
在执行 USB_SendData( )函数和 printf_usb( )函数时,
这两个函数已增加了判断电脑是否已正确识别到 USB 从设备的程序。
如果电脑要主动发送数据给 USB 从设备,电脑自己会主动判断与 USB 从设备是否已正确连接。
*/
set_usb_OUT_callback(usb_callback); //设置USB-CDC接收中断回调函数
EA = 1; //打开全局中断,一定要放在usb_init()的后面
DelayMsT(10); //延时10MS
while(1)
{
// 处理USB命令队列
if (cmdQueueHead != cmdQueueTail)
{
u8 idx = cmdQueueTail;
ProcessUsbCommand(cmdQueue[idx].dataBuf, cmdQueue[idx].len);
cmdQueueTail = (cmdQueueTail + 1) % CMD_QUEUE_SIZE;
}
Delay100us(1);
}
}
用这个USB-CDC 串口 中断方式接收上位机发来的命令处理数据有时上会机发送命令后CDC串口没有执行命令返回数据,丢失的命令是随机的,程序中只要接收命令数据就一定会返回数据给上位机, 上面是一部分代码,请帮忙分析原因
|
|