打印
[菜农助学交流]

[2012助学第一期]南信大瑜的学习笔记之USB控制LED灯

[复制链接]
5420|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 南信大瑜 于 2012-4-21 21:16 编辑

首先,我要感谢大叔,能给我这
个学习芯唐
M0的机会,我会记录自己的学习过程,与大家分享,由于我也是初学者,所以如果大家发现我的笔记有什么错误之处,希望大家及时指正。


今天已经是收到大叔板子的第五天了,在这五天里,我了解了NCU120的一些基本知识,我发现芯唐的固件库使用起来非常的方便,相比STM32的固件库来说,配置简单,固件库函数非常容易看懂,非常容易上手。下面言归正传,来开始我的第一个程序:USB控制LED灯。
1.
为什么要学习USB呢?

USB的应用已经非常广泛,像打印机、U盘、数码相机、手机等等都采用USB接口,我感觉USB已经成为了现在消费电子,工业控制等领域不可缺少的一种接口。因此,我们要学习好USB
2. 功能描述:
NCU120集成了一个全速USB2.0控制器和收发器,支持control/bulk/interrupt/isochronous传输类型,我们可以使用它来与PC机进行通信。我的第一个程序就是要通过PC机控制助学板上四个LED的亮灭。
3. 如何开始?
  我个人感觉USB协议很复杂,我以前看过USB协议,但看到一半就放弃了,因为看不懂,越看越不懂。有时候光看协议,人会受不了的,最好的办法就是通过实验,来体会,来分析。
学习USB的入门程序应该就是HID设备了吧。
HIDHuman Interface Device)人机接口设备类别是Windows最早支持的USB类别。由其名称可以了解HID设备是计算机直接与人交互的设备,例如键盘、鼠标和游戏杆等。不过HID设备不一定要有人机接口,只要符合HID类别规范,就都是HID设备。
实现HID设备不需要我们自己编写驱动程序,这使USB通信变的简单了,但是HID设备的缺点是传输速度较慢,只适合数据传输较慢的场合。
4.MDK工程分析。


int main(void)
{
System_init();  //系统初始化函数
    Gpio_init();  //初始化IO口函数
Uart_init();  //初始化串口函数
printf("\r\n");
printf("------------------------------------------\r\n");
printf("--- NCU120 Board USB_Hid Demo By Gwgj  ---\r\n"); //打印开发板相关信息
printf("------------------------------------------\r\n");
   
HID_MainProcess();  //HID设备处理函数,在HID_API.c中定义
}
void System_init(void)
{
UNLOCKREG(); //由于一些寄存器具有写保护功能,所以在写寄存器前要首先
     //进行解锁
  SYSCLK->WRCON.XTL12M_EN = 1;    //使能外部12M晶振,也就是把PWRCON寄存器的XTL12M_EN位置1
    DrvSYS_Delay(5000);  //延时一段时间,等待外部12M晶振稳定
    DrvSYS_Open(48000000);  //打系统时钟设置为48MHZ,以进行USB通信
LOCKREG();
}
void Gpio_init(void)
{
DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT ); //把LED1的端口设置为输出
    DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT ); //把LED2的端口设置为输出
    DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT ); //把LED3的端口设置为输出
    DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT ); //把LED4的端口设置为输出
}
void Uart_init(void)
{
STR_UART_T sParam;  //定义一个STR_UART_T类型的结构体
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0); //把UART的时钟设置为外部12M晶振
/* Set UART Pin */
DrvGPIO_InitFunction(E_FUNC_UART0);  //初始化UART0对应的引脚
/* UART Setting */
    sParam.u32BaudRate   = 115200; //设置波特率为115200
    sParam.u8cDataBits   = DRVUART_DATABITS_8; //设置数据位为8位
    sParam.u8cStopBits   = DRVUART_STOPBITS_1; //设置停止位为1位
    sParam.u8cParity   = DRVUART_PARITY_NONE; //设置无奇偶校验位
    sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES; //设置接收FIFO触发等级为1字节
DrvUART_Open(UART_PORT0,&sParam); //通过刚才配置的sParam参数来设置UART0
}

int32_t HID_MainProcess(void)
{
    int32_t i32Ret = E_SUCCESS;
    E_DRVUSB_STATE eUsbState;
    i32Ret = DrvUSB_Open(0);  //初始化USB设备,包括初始化USB SRAM,初始化状态等
    if (i32Ret != E_SUCCESS)
        return i32Ret;
    while (1)
    {
        _DRVUSB_ENABLE_MISC_INT(0); //禁止 USB-related 中断
        _DRVUSB_ENABLE_FLDET_INT(); //使能 float-detection 中断
        // 等待USB连接
        while (1)
        {
            // Order here is significant.
            // Give a chance to handle remaining events before exiting this loop.
            eUsbState = DrvUSB_GetUsbState();//获取USB状态
            //DrvUSB_DispatchEvent();
           if (eUsbState >= eDRVUSB_ATTACHED &&
                    eUsbState != eDRVUSB_SUSPENDED)
            {
                break;  //如果USB已经连接,跳出循环,结束等待
            }
        }
  
        //初始化HID设备,并把输入和输出报告定向到HID_GetInReport和HID_SetOutReport两个函数
  //这两个函数非常重要,我们就是要在HID_GetInReport和HID_SetOutReport两个函数中实现自己的功能,实现数据传输
        HID_Init((void *)HID_GetInReport, (void *)HID_SetOutReport);
        // 使能USB中断 INTEN_WAKEUP,INTEN_WAKEUPEN,INTEN_FLDET,INTEN_USB和INTEN_BUS
        _DRVUSB_ENABLE_MISC_INT(INTEN_WAKEUP | INTEN_WAKEUPEN | INTEN_FLDET | INTEN_USB | INTEN_BUS);
        // 查询和处理USB事件
        while (1)
        {
            eUsbState = DrvUSB_GetUsbState(); //获取USB状态
            DrvUSB_DispatchEvent();//分发,处理USB事件
            if (eUsbState == eDRVUSB_DETACHED) //如果USB断开了,跳出循环,重新等待USB链接
            {
    printf("USB Disconnected...\r\n");
                break;
            }
        }
        // Disable USB-related interrupts.
        _DRVUSB_ENABLE_MISC_INT(0);   //禁止USB-related中断
    }
}
//HID_SetOutReport函数用于处理输出报告
//我们在这里分析上位机发送的数据,并根据相应的数据进行相应的操作
//收到 1 时:点亮LED 1
//收到 2 时:点亮LED 2
//收到 3 时:点亮LED 3
//收到 4 时:点亮LED 4
//收到 5 时:熄灭LED 1
//收到 6 时:熄灭LED 2
//收到 7 时:熄灭LED 3
//收到 8 时:熄灭LED 4
void HID_SetOutReport(uint8_t *pu8EpBuf)
{
uint8_t i;
    uint32_t u32Size = (uint32_t)pu8EpBuf[1]; //pu8EpBuf[1]为收到数据的长度,由于我们上位机中每次都只发送一个字节,
             //所以在这里不需要对数据的长度进行判断,如果上位机中发送的数据长度不是恒定的
             //就要首先获取pu8EpBuf[1],再做相应的处理了
uint8_t cmd=pu8EpBuf[2]; //pu8EpBuf[2]就是我们收到的上位机传来的数据了
switch(cmd) //根据上位机发送的数据来进行点亮和熄灭LED的操作
{
  case 1:
   DrvGPIO_ClrBit(E_GPA,2);
   break;
  case 2:
   DrvGPIO_ClrBit(E_GPA,3);
   break;
  case 3:
   DrvGPIO_ClrBit(E_GPA,4);
   break;
  case 4:
   DrvGPIO_ClrBit(E_GPA,5);
   break;
  case 5:
   DrvGPIO_SetBit(E_GPA,2);
   break;
  case 6:
   DrvGPIO_SetBit(E_GPA,3);
   break;
  case 7:
   DrvGPIO_SetBit(E_GPA,4);
   break;
  case 8:
   DrvGPIO_SetBit(E_GPA,5);
   break;
  default:
   break;
}
}



//下位机的程序就结束了,由于芯唐提供了USB固件库,因此我们自己只写了几行代码就OK了,呵呵。

5.上位机程序分析。
虽然小弟以前也学过MFC,但是几年没用,已经忘的差不多了,今天就先不用MFC了,先建立一个命令行的工程,测试一下系统的功能,日后再改成MFC吧,真后悔当时没有好好学MFC啊。
开发环境为VS2005
 
#include "stdafx.h"  
#include "conio.h"
#include "Hid.h"
int _tmain(int argc, _TCHAR* argv[])  //主函数
{
CHidCmd io; //定义一个CHidCmd类型的对象
unsigned char cmd[]={0x00}; //定义一个数组,数组中存放要发送的数据
unsigned long Length;
    char user_cmd=0;
printf("----------------------------------------------\n");
printf("-- NUC120助学板 USB HID Demo   By 南信大瑜  --\n"); //打印一些相关信息
printf("----------------------------------------------\n");
printf("\n");
printf("->请进行功能选择:\n");
//打印一些帮助信息
printf("1 打开led1\n");
printf("2 打开led2\n");
printf("3 打开led3\n");
printf("4 打开led4\n");
printf("5 关闭led1\n");
printf("6 关闭led2\n");
printf("7 关闭led3\n");
printf("8 关闭led4\n");
printf("9 退出程序\n");

if(!io.OpenDevice(0x051A,0x511B)) //打开HID设备,第一个参数为VID,第二个参数为PID
{
  printf("->USB 设备打开失败,请检查助学板是否正确连接\n");
  user_cmd='9';
}
else
{
  printf("->USB 设备打开成功\n");
}


while(user_cmd!='9')  //如果用户输入‘9’,退出程序
{
  user_cmd=getch();
  
  switch(user_cmd) //如果用户输入的是'1'-'8',则通过USB发送相应命令到助学板
  {
  case '1':
    cmd[0]=0x01;
    printf("\n");
    printf("-->打开LED 1\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '2':
    cmd[0]=0x02;
    printf("\n");
    printf("-->打开LED 2\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '3':
    cmd[0]=0x03;
    printf("\n");
    printf("-->打开LED 3\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '4':
    cmd[0]=0x04;
    printf("\n");
    printf("-->打开LED 4\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '5':
    cmd[0]=0x05;
    printf("\n");
    printf("-->关闭LED 1\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '6':
    cmd[0]=0x06;
    printf("\n");
    printf("-->关闭LED 2\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '7':
    cmd[0]=0x07;
    printf("\n");
    printf("-->关闭LED 3\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '8':
    cmd[0]=0x08;
    printf("\n");
    printf("-->关闭LED 4\r\n\n");
    io.WriteFile((const char *)&cmd,sizeof(cmd),&Length,2000);
    break;
  case '9':
    printf("-->程序退出\n\n");
  default:printf("\n");
    printf("-->输入错误,请重新输入 >__< \n");
    printf("\n");
    break;
  }
  printf("->请进行功能选择:\n");

  printf("1 打开led1\n");
  printf("2 打开led2\n");
  printf("3 打开led3\n");
  printf("4 打开led4\n");
  printf("5 关闭led1\n");
  printf("6 关闭led2\n");
  printf("7 关闭led3\n");
  printf("8 关闭led4\n");
  printf("9 退出程序\n");
  
  
}
io.CloseDevice(); //关闭设备
return 0;
}
undefined















USB_Hid.rar

1.13 MB

PC_USB_Hid.rar

3.34 MB

相关帖子

沙发
南信大瑜|  楼主 | 2012-4-21 15:02 | 只看该作者

使用特权

评论回复
板凳
xyz549040622| | 2012-4-22 08:05 | 只看该作者
USB还没玩,顶

使用特权

评论回复
地板
hotpower| | 2012-4-22 08:13 | 只看该作者
很好

使用特权

评论回复
5
nwx8899| | 2012-4-22 16:41 | 只看该作者
支持楼主:)

使用特权

评论回复
6
hotpower| | 2012-4-22 18:06 | 只看该作者
104709
南信大瑜 发表于 2012-4-21 15:02


你可以用HotISP替代

使用特权

评论回复
7
[惊涛骇浪]| | 2012-4-25 23:18 | 只看该作者
霸气啊

使用特权

评论回复
8
lixiaoxu2meng| | 2012-4-26 09:58 | 只看该作者

使用特权

评论回复
9
yongjun_meng| | 2012-4-26 22:37 | 只看该作者
谢谢分享!!!!

使用特权

评论回复
10
plc_avr| | 2012-4-27 06:14 | 只看该作者
这个不错,顶!

使用特权

评论回复
11
ji7411| | 2012-4-27 07:08 | 只看该作者
不错,顶楼主个。!

使用特权

评论回复
12
chenshichao541| | 2012-4-27 08:35 | 只看该作者
不错,顶一个

使用特权

评论回复
13
abin0415| | 2012-4-29 02:47 | 只看该作者
LZV5

使用特权

评论回复
14
lwslws201| | 2012-5-6 18:57 | 只看该作者
还行把!

使用特权

评论回复
15
tanghaikun| | 2012-8-21 15:00 | 只看该作者
本帖最后由 tanghaikun 于 2012-8-21 15:06 编辑

不知道为什么PC端的软件用不了。

使用特权

评论回复
16
tao0127| | 2012-9-21 18:09 | 只看该作者
15# tanghaikun
我也是出现这个错误

使用特权

评论回复
17
slim443| | 2012-9-25 17:04 | 只看该作者
楼主程序不错

使用特权

评论回复
18
alwen| | 2012-9-25 23:15 | 只看该作者
不错,顶楼主个。!

使用特权

评论回复
19
tanghaikun| | 2012-9-27 15:59 | 只看该作者
不知道为什么PC端的软件用不了。119978
tanghaikun 发表于 2012-8-21 15:00

呼叫楼主,有问题!

使用特权

评论回复
20
ahljj| | 2012-11-18 15:02 | 只看该作者
看看。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

27

帖子

1

粉丝