Gamepad & WSN

Tag Archives: 单片机

混淆的c语言知识点:sizeof关键字

Author:Gamepader    IN:碎碎念    Tags: ,     评论: 0    超过41人围观

首先申明:sizeof是32个c语言关键字中的一个,它是关键字,不是函数!
下列测试基于以下平台:
Windows7,P3处理器(32bit),编译器:

1
2
3
4
5
6
7
8
9
10
11
12
$ gcc -v
Reading specs from /usr/lib/gcc/i686-pc-cygwin/3.4.4/specs
Configured with: /usr/build/package/orig/test.respin/gcc-3.4.4-3/configure --ver
bose --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --libe
xecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-langu
ages=c,ada,c++,d,f77,pascal,java,objc --enable-nls --without-included-gettext --
enable-version-specific-runtime-libs --without-x --enable-libgcj --disable-java-
awt --with-system-zlib --enable-interpreter --disable-libgcj-debug --enable-thre
ads=posix --enable-java-gc=boehm --disable-win32-registry --enable-sjlj-exceptio
ns --enable-hash-synchronization --enable-libstdcxx-debug
Thread model: posix
gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

example 1:

    1
    2
    void *p = NULL;
    printf("void *p = NULL;\tsizeof(p)=%d",sizeof(p));

    输出为:void *p = NULL; sizeof(p)=4

    1
    2
    int *p = NULL;
    printf("int *p = NULL;\tsizeof(p)=%d",sizeof(p));

    输出为:int *p = NULL; sizeof(p)=4

example 2:

    1
    2
    3
    4
    5
    int a[100];
    printf("int a[100];\tsizeof(a)=%d\n",sizeof(a));
    printf("int a[100];\tsizeof(a[100])=%d\n",sizeof(a[100]));
    printf("int a[100];\tsizeof(&a)=%d\n",sizeof(&a));
    printf("int a[100];\tsizeof(&a[0])=%d\n",sizeof(&a[0]));

    输出为:
    int a[100]; sizeof(a)=400
    int a[100]; sizeof(a[100])=4
    int a[100]; sizeof(&a)=4
    int a[100]; sizeof(&a[0])=4

example 3:

    1
    2
    3
    int i = -20;
    unsigned j = 10;
    printf("i+j=%d",i+j);

    输出为:
    i+j=-10

example 4:

    const volatile value表示不应修改value的值,但是value的值可能随时会被外部(如:硬件)修改。
    volatile标识一个变量意味着这个变量可能被非本程序的其他过程改变,例如某个访问这一变量的某中断程序。为变量加上这一标识可以禁止编译器的优化,使程序正确地按设计者的意图运行。
    如果一个变量不会被本程序改变,通常可能给它加上const,但如果该变量可能被其他程序改变而本程序又在检测这个变量的值,就需要给它加上volatile,于是变量就同时有volatile和const了。
01-30
2013

C语言中宏定义的一个特殊用法

Author:Gamepader    IN:ARM_Linux    Tags: ,     评论: 0    超过49人围观

在程序调试时,我们经常需要输出一些调试信息,当调试完毕后,就不再需要使用了。那怎么快速的在调试状态和发布状态切换呢?通常我们使用预编译加宏定义来处理这个问题,例如:

1
2
3
#ifdef DEBUG
调试代码
#endif

如果我们使用printf来显示一些调试信息,那么每个地方都加上#ifdef和#endif就很麻烦了。我们可以定义一个DbgPrintf的函数来专门处理这些事情,只在DbgPrintf函数内放上#ifdef和#endif就行了。但是这样代码在运行时,还是有调用一次函数的,浪费了时间。那么可不可以利用宏定义,实现完全没有编译代码产生的宏呢?
可以尝试下面的宏代码:

1
2
3
4
5
6
#ifdef DEBUG
#define DbgPrintf printf
#else
#define DbgPrintf /\
/DbgPrintf

#endif

如果DEBUG已经定义了,那么不用说,当然是用printf去代替DbgPrintf了。
下面只分析DEBUG未定义的情形,这个宏定义实际上是将“DbgPrintf”定义成了“//DbgPrintf”,由于续行符的作用,#define定义时不会发现注释符“//”,但是在展开到代码之后,就成了注释符“//”了,也就是说,如果你原来的代码是DbgPrintf("%d",x);,经过这个宏展开后成了//DbgPrintf("%d",x);,相当于自动在前面加了注释符“//”。要注意的是,续行符后面的“/”一定要顶格写,否则就不是“//”了。另外,这个宏只能单独一行使用,因为它将该行后面的代码都注释掉了。
(转载自computer00)

01-30
2013

LibUSB通过SetReport()请求与USBHID设备通信

Author:Gamepader    IN:手柄    Tags: , , ,     评论: 0    超过198人围观

自从基于libUSB的USB设备固件更新程序(下载数据)之后,好久没时间继续我的USB折腾了。今天继续。
本文开发环境:Win7
上位机编译环境:VC++ Express 2010
libusb-win32-devel-filter-1.2.6
首先,安装所需要控制的设备的LibUSB-Win32 Filter,注意:不是LibUSB-Win32本身啊,否则LibUSB驱动程序或替代M$的默认USBHID类设备驱动程序,结果是USBHID设备没有反应。
然后,开始编写上位机程序:
按照LibUSB文档说明的操作顺序,先打开设备:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//此处VID、PID为测试用,工业生产请勿使用,如有冒犯贵公司,请及时指出以便我们修改
#define MY_VID 0x0666
#define MY_PID 0x0001
#define MY_CONFIG 0x01
usb_init(); /* initialize the library */
usb_find_busses(); /* find all busses */
usb_find_devices(); /* find all connected devices */
if(!(dev = open_dev())) {
printf("error opening device: \n%s\n", usb_strerror());
printf("Is your USB-Device successfully pluged in?\n\n");
}
else {
printf("success: device %04X:%04X opened\n", MY_VID, MY_PID);
}
if(usb_set_configuration(dev, MY_CONFIG) < 0) {
printf("error setting config #%d: %s\n", MY_CONFIG, usb_strerror());
printf("Is your USB-Device running?\n\n");
usb_close(dev);
}
else
{
printf("success: set configuration #%d\n", MY_CONFIG);
}

if(usb_claim_interface(dev, 0) < 0) {
printf("error claiming interface #%d:\n%s\n", MY_INTF, usb_strerror());
printf("Please check your USB-Device's firmware!\n\n");
usb_close(dev);
}
else {
printf("success: claim interface #%d\n", MY_INTF);
}

此时已经成功打开设备的接口1。接下来,可以发送SetReport()请求。
根据USB HID协议规范,Set Report()请求总长8个字节,分为bmRequestType、bRequest、wValue(2 bytes)、wIndex(2 bytes)、wLength(2 bytes)。需要注意的是,USB请求都是低位在前,也就是说,一个WORD的低8位先传输,高8位后传输。这8个字节的请求之后,通过Control transfer 的 Output端点下发数据。

  • bmRequestType=0x21;表示USBHID类请求;
  • bRequest=0x09;表示SetReport()请求;
  • wValue=0x0003;Report ID = 0,Report Type = 0x03(01:Input,02:Output,03:Feature,04-ff:Reserved)表示通过Feature Report发送数据(USB键盘的LED是通过Output Report发送的数据)。
  • wIndex=0x0000;表示选择端点0。
  • wLength=0x0300;表示数据长度是3 bytes

接下来通过控制传输的输出端点发送3 bytes的数据:char ShiftMouseScrollDown1[] = {0x02,0xf3,0xff};

具体在LibUSB中,是使用usb_control_msg()函数实现的,该函数的原型为:

1
2
3
4
int usb_control_msg(usb_dev_handle *dev,
        int requesttype, int request,
        int value, int index, char *bytes, int size,
        int timeout);

usb_control_msg 函数在默认控制管道发送控制请求,该函数的参数符合标准USB的数据规范。
对照上方的数解释,构建出这些函数参数

1
2
3
4
5
6
7
8
9
10
    ret = usb_control_msg(dev, 0x21, 0x09,
                0x0300, 0x0000, ShiftMouseScrollDown1, 3,
                1000);//1000 ms timeout
    if(ret < 0) {
        printf("error writing:\n%s\n", usb_strerror());
    }
    else
    {
        printf("success! COMMAND sent in %d bytes\n", ret);
    }

至此,数据发送完成。通过Bus Hound软件应该可以捕捉到传输的数据。
需要多次发送的话,多次调用usb_control_msg()即可。
发送完成之后的关闭USB接口操作,

1
2
    usb_release_interface(dev, MY_INTF);
    usb_close(dev);

一些基础细节,请参考我之前的博文
基于libUSB的USB设备固件更新程序

可能出现的问题:

  1. 不小心安装了LibUSB-Win32驱动程序,此时不要惊慌,直接使用USBDeview这个小软件,找到对应的设备,卸载(其驱动程序),重新拔插一次设备即可恢复系统驱动。
12-24
2012
loading...