shootingstars

菩提本无树,明镜亦非台。本来无一物,何处惹尘埃。尘埃乃虚幻,亦何惧之来?

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  30 随笔 :: 0 文章 :: 48 评论 :: 0 引用

2010年7月30日 #

GPIO:

与单片机类似,GPIO就是芯片的引脚,管脚是可编程的

可对引脚的工作模式进行设置:输入模式(检测输入信号),输出模式(输出0或1),(通过寄存器)
高阻状态(常用于AD转换),还有禁止或允许上内部下拉电阻(上拉:管脚通过电阻接高电平,
下拉:管脚通过电阻接地,也可以外部接上拉或下拉电阻),还要管脚复用等功能,即通过
对内部寄存器的设置使引脚既可以工作在一般模式,作为普通的GPIO口使用,
也可已工作在特殊模式,比如作为外部中断信号输入引脚等等。如果不设置GPIO引脚,CPU

工作时有一个初始化模式,可以从datasheet上了解。

 

I2C: 

I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。

同时,它也是一种协议,我们可以通过其他手段模拟出I2C协议来(比如GPIO)。

相关附件

 

PWM: 

PWM(Pulse Width Modulation)——脉宽调制,是一种开关式稳压电源应用,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。

简而言之,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。 

相关链接

 

posted @ 2010-07-30 18:12 shootingstars 阅读(27) 评论(0) 编辑

2010年1月11日 #

 

我们有些时候需要存储一些函数以备后用,最常用的就是C中的Callback。。。
但是到了C++年代,函数都放到了类中,想要Callback就有些复杂了。Boost::function封装了一个模版库,它可以接受静态函数,普通函数以及仿函数,为了了解它的原理,我自己试图写一个简单的类。。。

我们先看boost中function的使用
boost::function<int(int)> func; // 能接受int(int)型的函数或仿函数
在模版参数中我们看到int(int) ,这个可能一般用户感到陌生,其实它是一个函数类型,表示返回值是int,并且有一个参数是int的函数类型。
一直以来令我感到困惑的是:int(int)仅仅是一个类型,一般而言我们如果需要用模版接受这个参数的话,可以这么用
template <class F>
class Function
问题是这样的话,所有的返回值和参数(个数)信息会全部丢失,这样在Function中的operator()就无法写出合适的调用形式。

一种方式是不用此种函数类型,而用多个模版参数。如
template <class Ret, class Param1>
class Function
此时很容易得到函数的返回值和参数(并且有些Function/Delegate库中确实是这么用的,Boost的可移植类型也是这么干的),但是这么做的话,用户可能看着不习惯。
我们来看看boost是如何做到用一个模板参数同时也可以得到函数类型的返回值和参数个数信息的。
答案就是模板偏特化
在boost中有一个根本未起作用的Function类
template<
typename Signature
>
class function;
但是它有多个偏特化的版本,其中一个如下:
template<typename R,typename P1>
class function<R(P1)>
这个模版偏特化了上述的模版,并且区分出了返回值和参数。嗯,现在我们可以做一个简单的Function看看好不好使
template <typename R, typename P1>
class Function<R(P1)>
{
    typedef R (
*fun)(P1);
public:
    Function()
    {
        m_function 
= NULL;
    }

    Function(fun f)
    {
        m_function 
= f;
    }
    
    R 
operator()(P1 p1)
    {
        
return m_function(p1);
    }

    
void operator=(fun f)
    {
        m_function 
= f;
    }
private:
    fun m_function;
};

int PrintInt(int i)
{
    printf(
"PrintInt=%d\n",i);
    
return i;
}

Function
<int(int)> fun(PrintInt);

int main(int argc, char* argv[])
{
    fun(
20);
    
return 0;
}
代码
template<
typename Signature
>
class Function;

template 
<typename R, typename P1>
class Function<R(P1)>
{
    typedef R (
*fun)(P1);
public:
    Function()
    {
        m_function 
= NULL;
    }

    Function(fun f)
    {
        m_function 
= f;
    }
    
    R 
operator()(P1 p1)
    {
        
return m_function(p1);
    }

    
void operator=(fun f)
    {
        m_function 
= f;
    }
private:
    fun m_function;
};

int PrintInt(int i)
{
    printf(
"PrintInt=%d\n",i);
    
return i;
}

Function
<int(int)> fun(PrintInt);

int main(int argc, char* argv[])
{
    fun(
20);
    
return 1;
}


继续,我们想包装一个类的成员变量,boost推荐的是如下调用方式:

boost::function<int (X*, int)> f;

表示此funtion接受一个类名为X,返回值为int,参数为int的函数。。。嗯,怎么看怎么不爽。。。为啥不用类的成员变量的表达方式呢--- int (FunClass::*)(int) ,也许是很多编译器不支持?

我们看看目前主流C++编译器是否支持此种类型。(vc2008和g++ 4.1.3)偏特化如下代码:

代码
template<
typename Signature
>
class Function;

template 
<typename R, typename P1, class T>
class Function<R (T::*)(P1)>
{
    typedef R (T::
*fun)(P1);
public:

    Function(T 
&t, fun f) : m_class(t)
    {
        m_function 
= f;
    }
    
    R 
operator()(P1 p1)
    {
        
return (m_class.*m_function)(p1);
    }

private:
    T   
&m_class;
    fun       m_function;
};

class FunClass
{
public:
    
int fun(int i)
    {
        printf(
"FunClass fun %d\n",i);
        
return i;
    }
};

int main(int argc, char* argv[])
{
    FunClass funclass;
    Function
<int (FunClass::*)(int)> fun(funclass, &FunClass::fun);
    fun(
123);
    
return 1;
}


哈哈,编译器老老实实通过了,结果也对。

 

 

 


posted @ 2010-01-11 18:10 shootingstars 阅读(100) 评论(0) 编辑

2010年1月8日 #

C可以支持可变参数,所有才会有printf一类的神奇函数。问题是它是怎么实现的?其实看完了va_list/va_start等宏的定义后,才会猛然知道,原来它是这么的简单。其实就是C把所有变量压入一个堆栈,在函数中再按前面的format的指示从堆栈中取出对应的值而已。

相关网页:http://ipe.gzu.edu.cn/kszx/jsj/jyjl1/200910/33758.html

 上述网页中提到的一个问题是关于可变参数的传递问题,其实它并没有解决。(不可能把printf的所有解析过程重写一遍)

这个问题其实非常常见,比如我们的Log想支持可变参数的时候,就很有可能需要传递可变参数

Log(const char *format, ...)

问题是我们怎么把这个可变参数传递给printf之类的函数呢?

其实C有一个函数

int vsnprintf(char *str, size_t size, const char *format, va_list args);
这个函数支持这种类型va_list args

 

我们可以这样写这个函数


代码
 Log(const char *format, ...)
{
    
char buf[512];
    va_list args;
    va_start(args, format);
    
int len = vsnprintf(buf, sizeof(buf), format, args);
    
// 你可以放一些printf之类的函数,或者直接写文件等等...
    va_end(args);

注意:Windows CRT的名字为_vsnprintf 

posted @ 2010-01-08 11:29 shootingstars 阅读(65) 评论(0) 编辑

2009年12月30日 #

SFINAE(匹配失败不是错误)

当模版函数匹配失败时,如果还有其他选择,就选择其他的重载函数,并且忽略这个编译错误。相关的有boost::enable_if

相关网页:http://www.cnblogs.com/coolzgx/archive/2009/12/16/1625425.html

 

posted @ 2009-12-30 17:51 shootingstars 阅读(42) 评论(0) 编辑

2009年12月15日 #

Mifare卡是一种非接触式的智能卡,我们了解他们的相关协议。

表一

命令格式如下:

协议头(Head):2字节,固定填充0xAA,0xBB

长度(Length):2字节,从此列后的所有有效字节数(包含XOR)

节点ID(Node ID):2字节,目标节点地址数

函数码(Function code):2字节,函数功能码,另见表三

数据(Data):00~D0字节,数据位

异或(XOR):1字节,从节点ID到最后一个自己的数据的异或值

 

表二

回复格式如下:

协议头(Head):2字节,固定填充0xAA,0xBB

长度(Length):2字节,从此列后的所有有效字节数(包含XOR)

节点ID(Node ID):2字节,目标节点地址数

函数码(Function code):2字节,函数功能码,另见表三

状态(Status):成功为0,其余的值为失败

数据(Data):00~D0字节,数据位

异或(XOR):1字节,从节点ID到最后一个自己的数据的异或值

 

 

 表三

函数码列表:

1、 Initialize port :0x0101
2、 Set device node number : 0x0102
3、 Read device node number : 0x0103
4、 Read device Mode : 0x0104
5、 Set buzzer beep: 0x0106
6、 Set Led color : 0x0107
7、 Set reader working status : 0x0108
8、 Set antenna status 。0x010c
9、 Mifare Reauest , 0x0201
10、 Mifare anticollision , 0x0202:
11、 Mifare Select 0x0203:
12、 Mifare Hlta , 0x0204:
13、 Mifare Authentication1 0x0206 :
14、 Mifare Authentication2 0x0207:
15、 Mifare Read 0x0208:
16、 Mifare Write 0x0209:
17、 Mifare Initval 0x020A:
18、 Mifare Read Balance 0x020B:
19、 Mifare Decrement 0x020C:
20、 Mifare Increment 0x020D:
21、 Mifare Restore 0x020E:
22、 Mifare Transfer 0x020F
23、 Mifare UltraLight Anticoll 0x0212:
24、 Mifare UltraLight Write 0x0213:
25、 Write key store in RC500 EEPROM 。

 

读取卡号流程:

1 设置串口波特率,参数如下:

Baud rate: 19200 bps
Data: 8 bits
Stop: 1 bit
Parity: None

2  打开天线

发送命令0x010c,数据1(打开天线)到串口

3 请求卡类型

发送命令0x0201,数据0x52到串口

 4 读取卡信息

发送命令0x202到串口

 

完成后,读取串口返回信息即可。

详细信息文档:/Files/shootingstars/MifarMifareProtocol.rar

posted @ 2009-12-15 15:18 shootingstars 阅读(213) 评论(0) 编辑

2009年12月14日 #

摘要: 一、前言:Wiegand(韦根)协议是由摩托罗拉公司制定的一种通讯协议,它适用于涉及门禁控制系统的读卡器和卡片的许多特性;其协议并没有定义通讯的波特率、也没有定义数据长度韦根格式主要定义是数据传输方式:Data0 和 Data1 两根数据线分别传输 0 和 1.现在应用最多的是 26bit,34bit等等。二、韦根数据输出的基本概念:韦根数据输出由二根线组成,分别是 DATA0 和 DATA1 ;...阅读全文
posted @ 2009-12-14 17:34 shootingstars 阅读(721) 评论(0) 编辑

2008年7月30日 #

摘要: 1 使用:一直以来习惯了使用printf函数,但是对于可变参数没有深入研究过,觉得可变参数是一个神奇的技术^0^。。。工作闲下来的时候,想研究研究看可变参数的使用和原理。目前C提供的可变参数的申明为void function(const char *format, ...);这样就可以在function中使用可变参数C提供了几个宏用于使用可变参数va_listva_startva_argva_en...阅读全文
posted @ 2008-07-30 14:05 shootingstars 阅读(257) 评论(0) 编辑

2008年7月22日 #

摘要: [代码]阅读全文
posted @ 2008-07-22 13:52 shootingstars 阅读(332) 评论(0) 编辑

2008年6月2日 #

摘要: 在Java中,继承类可以使用super访问基类中的数据变量Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->classA{inti=-1;}classBextendsA{voidprintSuperI(){System.out.println(super...阅读全文
posted @ 2008-06-02 09:23 shootingstars 阅读(581) 评论(0) 编辑

2008年5月7日 #

摘要: 编译程序一般划分为1 词法分析 -- 输入源程序,对源程序的字符串进行扫描和分解,得到一个个单词(token)2 语法分析 -- 按照语法规则,确定输入串是否符合此规则3 语义分析及中间代码产生 -- 在语法分析的基础上分析含义,并且进行相关的翻译(中间代码)。如很多编译器采用“四元式”作为中间代码,四元式如下所示: 算符 左操作数 右操作数 结果4 优化 -- 优化以上产...阅读全文
posted @ 2008-05-07 18:43 shootingstars 阅读(168) 评论(0) 编辑