0

关于投票
引用没有声明的外部函数可能会导致严重问题

using a function without a valid prototype is VERY dangeours.

    在一个函数中调用另外一个文件中定义的函数,但是这个函数没有进行声明,会出什么问题哪?

    大多数的情况下可能会出现问题,有些情况下,可能是幸运不会出现问题。

     看下面这段代码:

    unsigned long ulWater_Max_Value=0xABCDEFUL;

    Puthexbyte(ulWater_Max_Value>>24);
    Puthexbyte(ulWater_Max_Value>>16);
    Puthexbyte(ulWater_Max_Value>>8);
    Puthexbyte(ulWater_Max_Value);

    其中Puthexbyte函数在另外一个c文件中进行了定义,但是在该文件对应的.h文件中,我没有对这个函数进行声明。

    这样,当运行上面的代码的时候,会导致错误的结果,输出的数据全部为0。

    改正的方法是,为每个外部函数在.h文件做一个相应的声明。每个需要调用这个函数的文件都要包含这个.h头文件。

    仍然是上面的代码,如果把变量定义为unsigned int 形式,却可以输出正确结果。这有点奇怪,绝对是侥幸,但是,为什么会对哪?即:

    unsigned int ulWater_Max_Value=0xABCD;

    //Puthexbyte(ulWater_Max_Value>>24);
    //Puthexbyte(ulWater_Max_Value>>16);
    Puthexbyte(ulWater_Max_Value>>8);
    Puthexbyte(ulWater_Max_Value);

    在不声明Puthexbyte函数的情况下,仍然能正确输出,为什么哪?

系统分类: 单片机
用户分类: 学习设计
标签: 无标签
来源: 原创
发表评论 阅读全文(397) | 回复(1)

0

关于投票
开发中如何使用WinCVS

什么是CVS,为什么要使用它。

    CVS是个版本控制系统,使用它你可以记录你源代码文件的历史。 
例如,当软件修改时有时会产生问题(*bugs这里被译为问题),并且你可能在做这  次修改后很长时间不会发现这些问题。使用CVS,你可以容易地回顾老的代码版本去  发现哪一次的修改导致这些问题。有时候这样会非常有帮助。 
  
    你可能会保留你每一次的代码版本,这可能会浪费你很多的代码空间。CVS使用一种聪明的办法保存你的多个版本在一个文件中。它仅仅保留版本间的不同内容。如果你是一个项目中的一组成员之一,CVS也能够帮助你。除非你特别仔细,你很容易覆盖其他人的工作。一些编辑器,例如GNUEmacs,试图去判定一个文件是否被两人同时修改。不幸的是,如果一个人使用其它的编辑器时,这个安全方式将不再有效。CVS使用让不同开发者独立工作的方式解决了这个问题。每一个开发者的工作都在他自己的目录内,并且CVS将在每个开发者的工作完成后进行合并工作。

如何使用它?

    还是先要现在软件来装,wincvs可以在http://sourceforge.net/projects/cvsgui/
上下载,下载后一路next就可以了。

    安装完成后,第一次运行有可能还让你安装puthon。听话下载安装就是了。如果服务器端已经弄好,客户端就可以连接使用了,下面先简单介绍。
The basic usage of WinCVS is very simple. Start the software.

1) Use Admin/Login and enter the settings.(主要是输入服务器的地址和密码)
2) Checkout the project.
---- Working with CVS
* You can add files to the CVS Root by clicking on them and selecting
Add. After you have added them right click them and commit them.
* You can commit changes on files by clicking on commit. In this case
changes becomes permanent.

----- Benefits of CVS
* CVS is a version control software. You can see the difference between
source files. You can also tag software releases so that you can
reproduce them later.

关于WinCvs和CVS的介绍

下面给出一些介绍CVS的链接,解释CVS的历史和用法。

http://blog.csdn.net/wangjiliang/archive/2004/09/16/106179.aspx

http://www.chedong.com/tech/cvs_card.html

系统分类: 嵌入式
用户分类: 学习设计
标签: 无标签
来源: 原创
发表评论 阅读全文(173) | 回复(0)

0

关于投票
双电源切换电路

    系统设计中常常会碰到有双电源供电的情况。其中一个是主电源,而另外一个是备用电源(通常为电池)。

    在设计中往往需要实现电池与主电源的隔离,而采用MOS管是一种很有效的方式。附件是在双电源设计中可以使用的电路。详细分析了一种双电源切换电路的原理。并且给出了设计的心得。

    描述的可能有不对的地方,请多指教。

点击下载

系统分类: 嵌入式
用户分类: 学习设计
标签: 双电源切换
来源: 原创
发表评论 阅读全文(378) | 回复(0)

0

关于投票
采用SHT11与ATMEG168制作温湿度传感器

    SHT11是一款由瑞士Sensirion公司生产的智能型温湿度传感器,该传感器是数字式的输出接口,具有免调试、低功耗、高可靠性和全互换的特点。

    ATMEG168是一款便宜的低功耗8位单片机,应用非常广泛,又有免费的编译器GCC(WINAVR),在线编程工具也很便宜。

    我们将一步一步完成基于这两个芯片的温湿度传感器的设计。

    第一,查询资料

      1,中文简介:

http://www.7613.com/wen/wen_app/sensapp/l05032501.pdf

       2,已经有的原型设计:

 http://www.ondre.de/index.php?section=sht&PHPSESSID=qvaejoph47pql1k7cns8b90db6

    第二,分析工作量

    硬件的连接很方便,由于数字接口跟IIC不兼容,所以不能用硬件IIC来接口。软件部分,上面的原型设计中有c代码,只需要调试通过即可。

    第三,硬件设计

    参考已经有的原型设计,可以将SHT11的DATA和SCK接到mega168的任意两个双向I/O口上。485电路和mega168的外围电路可以参考各种经典示例电路。

    第四,SHT11驱动程序

    借鉴已有的驱动程序,下面贴出能用的源代码:驱动包括头文件和c文件。

     头文件如下:

//sht11.h
#ifndef _MB_MR_POUT_H
#define _MB_MR_POUT_H

#ifdef __cplusplus
PR_BEGIN_EXTERN_C
#endif

void ConnReset(void);
unsigned char measure(unsigned int *p_value, unsigned char *p_checksum, unsigned char mode);

enum {TEMP, HUMI};

#ifdef __cplusplus
PR_END_EXTERN_C
#endif
#endif
源代码C文件如下:

/* ----------------------- System includes ----------------------------------*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <util/delay.h>
#include <avr/interrupt.h>//////

/* ----------------------- Platform includes --------------------------------*/
#include <avr/io.h>

#include <Common.h>
#include <Utils.h>
#include <DrvSht11.h>

/* ----------------------- Defines ------------------------------------------*/
#define noACK 0
#define ACK 1

#define STATUS_REG_W  0x06
#define STATUS_REG_R  0x07
#define MEASURE_TEMP  0x03
#define MEASURE_HUMI  0x05
#define RESET         0x1e

/*
#define setREAD       outb(DDRB, 0x01); sbi(PORTB, 1)
#define setWRITE      outb(DDRB, 0x03)
#define SCK(i)        if (i) sbi(PORTB, 0); else cbi(PORTB, 0)
#define DATA(i)       if (i) sbi(PORTB, 1); else cbi(PORTB, 1)
*/


#define setREAD       DDRD |=(1<<PD3); PORTD|=(1<<PD4);DDRD &= ~(1<<PD4)
#define setWRITE      DDRD |=(1<<PD3); DDRD |=(1<<PD4)
#define SCK(i)        if (i) PORTD|=(1<<PD3); else PORTD &= ~(1<<PD3)
#define DATA(i)       if (i) PORTD|=(1<<PD4); else PORTD &= ~(1<<PD4)


/*#define setREAD       DDRD |=(1<<PD4); PORTD|=(1<<PD3);DDRD &= ~(1<<PD3)
#define setWRITE      DDRD |=(1<<PD4); DDRD |=(1<<PD3)
#define SCK(i)        if (i) PORTD|=(1<<PD4); else PORTD &= ~(1<<PD4)
#define DATA(i)       if (i) PORTD|=(1<<PD3); else PORTD &= ~(1<<PD3)
*/

//  enum {TEMP, HUMI};

/******************************************
* 名称    :  Init_Timer0
* 功能描述:  定时器0初始化函数
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法:  产生尽量长的定时,用来计算一段时间内是否有脉冲
--------------------------*/
/*void UART_Init() {
  outb(UBRR, UBRRVAL);  // Baudrate einstellen
  sbi(UCR,TXEN);        // TX aktivieren
}

void UART_SendChar(char s) {
  loop_until_bit_is_set(USR, UDRE);
  outb (UDR, s);
}

void UART_SendStr(char *s) {
  while (*s) {
    loop_until_bit_is_set(USR, UDRE);
    outb (UDR, *s++);
  }
}
*/
void delay_us(unsigned int us) {
  while (us)
  {
     _delay_us(10);
     us--;
   }
}


/******************************************
* 名称    :  延时
* 功能描述:  定时器0初始化函数
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
void delay_ms(unsigned int ms) {
  unsigned int outer1, outer2;
  outer1 = 2000;
  while (outer1) {
    outer2 = 10000;
    while (outer2) {
      while ( ms ) ms--;
      outer2--;
    }
    outer1--;
  }
}


/******************************************
* 名称    :  TransStart
* 功能描述:  开始传输
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法:  产生尽量长的定时,用来计算一段时间内是否有脉冲
--------------------------*/
void TransStart(void)
{
  DATA(1);//数据位置1 
  SCK(0);//sck清0
  delay_us(1);//延时
  SCK(1);//sck置1
  delay_us(1);//延时
  DATA(0);//数据变低
  delay_us(1);//延时
  SCK(0);//sck降低
  delay_us(5);//延时
  SCK(1);//sck置高
  delay_us(1);//延时
  DATA(1);//数据置高
  delay_us(1);//延时
  SCK(0);//sck清0
  delay_us(1);//延时
}

/******************************************
* 名称    :  ConnReset
* 功能描述:  复位连接,data为高,不断翻转sck
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
void ConnReset(void)
{
  unsigned int i;
  setWRITE;
  delay_us(1);//延时
  DATA(1); SCK(0);
  for(i=0; i<9; i++) {
    SCK(1);
 delay_us(1);//延时
    SCK(0);
 delay_us(1);//延时
  }
  delay_us(1);//延时
  TransStart();//发送开始信号
}

/******************************************
* 名称    :  GetDATA
* 功能描述:  获取数据,看这个位是高还是低
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
unsigned int GetDATA()
{
  return bit_is_set(PIND, PD4);
}

/******************************************
* 名称    :  WriteByte
* 功能描述:  写字节
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
unsigned char WriteByte(unsigned char value) {
  unsigned char i, error="0";
  setWRITE; 
  delay_us(1);//延时                //设置为写
  for(i=0x80;i>0;i/=2)
  {
    if (i & value) DATA(1);//先输出最高位
    else DATA(0);
 delay_us(1);//延时
    SCK(1);                 //产生一个下降沿
    delay_us(5);
    SCK(0);
 delay_us(1);//延时
  }
  delay_us(1);//延时
  setREAD;                  //设置为读
  delay_us(1);//延时
  SCK(1);                   //SCK设置为高
  delay_us(1);              //延时
  error="GetDATA"();          //获取SCK数据
  SCK(0); 
  delay_us(1);//延时                
  return error;
}


/******************************************
* 名称    :  ReadByte
* 功能描述:  读字节
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
unsigned char ReadByte(unsigned char ack) {
  unsigned char i,val=0;
  setREAD;                 //设置为读
  delay_us(1);//延时
  for(i=0x80;i>0;i/=2)
  {
    SCK(1);                //置高
 delay_us(1);//延时
    if (GetDATA()) val=(val | i);  //获取数据
    SCK(0);                        //拉低
 delay_us(1);//延时
  }
  delay_us(1);//延时
  setWRITE;                        //设置为写
  delay_us(1);//延时
  DATA(!ack);
  delay_us(1);//延时
  SCK(1);
  delay_us(5);
  SCK(0);
  delay_us(1);//延时
  return val;
}


/******************************************
* 名称    :  Conv_byte
* 功能描述:  转换数据
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
/*
void Conv_byte(unsigned char in, unsigned char *out)
{
  unsigned char a;
  a="in"&0xf0;
  a="a">>4;
  if(a>9) {
    out[0]=a-10+0x41;
  } else {
    out[0]=a+0x30;
  }
  a="in"&0x0f;
  if(a>9) {
    out[1]=a-10+0x41;
  } else {
    out[1]=a+0x30;
  }
}

void conv_int(int in, unsigned char * out) {
  unsigned int temp;
  unsigned char a;
  if(in>=0) {
    temp="in"&0xff00;
    a=(unsigned char)(temp>>8);
    conv_byte(a,out);
    a=(in&0x00ff);
    conv_byte(a,out+2);
  } else {
    *out='-';
    out++;
    in*=-1;
    temp="in"&0xff00;
    a=(unsigned char)(temp>>8);
    conv_byte(a,out);
    a=(in&0x00ff);
    conv_byte(a,out+2);
  }
}
*/

/******************************************
* 名称    :  Conv_byte
* 功能描述:  转换数据
* 输入参量: 
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
unsigned char measure(unsigned int *p_value, unsigned char *p_checksum, unsigned char mode) {
  unsigned char lsb,msb,check;
  unsigned char error="0";
  unsigned int i,t;

//cli();//////////////////////////////
  TransStart();//开始传输
  switch(mode) //发送温度或者湿度
  {
    case TEMP : error+=WriteByte(MEASURE_TEMP); break;
    case HUMI : error+=WriteByte(MEASURE_HUMI); break;
    default   : break;
  }
  setREAD;     //设置为读


  for(i=0;i<65535;i++)
  {
   _delay_ms(1);
    if (GetDATA()==0)
    break;//等待DATA电平变高
  }
  if (GetDATA())
  {
      error+=1;  //如果变高,加1
   }
 

 *p_value = ReadByte(ACK); //读字节
  *p_value<<=8;
  *p_value+= ReadByte(ACK);//再读一个字节
/*
*(p_value+1)  =ReadByte(ACK);    //read the first byte (MSB) 
  *(p_value)=ReadByte(ACK);    //read the second byte (LSB) 

*/
  *p_checksum = ReadByte(noACK);//读CRC
//sei();//////////////////////////////

  return error;
 
}


    更近一步的,如果为这个小系统增加modbus从协议栈的支持。那么这模块就可以变成modbus智能温湿度传感器模块,该模块中温度湿度和露点都分别对应一个寄存器。通过标准的modbus协议就可以对这个模块进行读数了。

 

------------

在sht11的官方网站,有一个针对sht11的例子程序,这个程序针对的mcu是8051系列的cpu。当应用到avr上时候,需要注意延时。

特别的,在函数measure中,有个延时等待信号变低的语句:  for(i=0;i<65535;i++) if (GetDATA()==0) break;//等待DATA电平变低

如果avr跑10M的化,这个时间内不能转换完成,需要增加一条延时语句。如,可以写成这样:

  for(i=0;i<65535;i++)

{

   _delay_ms(1);////////////////////////////////////////////////////////////增加的延时语句

    if (GetDATA()==0) break;//等待DATA电平变低

}

 

 

系统分类: 嵌入式
用户分类: 学习设计
标签: 无标签
来源: 原创
发表评论 阅读全文(289) | 回复(0)

0

关于投票
传统的复位电路

传统的复位电路如下所示:

现在再好好分析一下:

1,二极管D501的用途

如果没有D501,当断电后又立刻上电,电容上的电荷不能放完,则无法正常复位。当,当系统断电时,VCC负载很重,所以下降的很快,而C502负载轻,所以下跌的慢,加上D501时,VCC下降,电容就会会跟着下降,复位端电压会跟着迅速下降。

2,U502F的输入为什么接地

CMOS输入不能为空,可以接地或者VCC。

3,为什么用74HC14而不用普通的74HC04

74HC14是带有施密特触发器的非门。电容放电信号不是数字信号,而是“连续缓慢”的模拟信号,需要用施密特触发器把模拟信号整型为方波数字信号。这跟数字信号记过国长距离传送后需要整型是同一个道理。

4,为什么“非来非去”

首先让外设先复位,然后让CPU芯片复位,保证CPU和外设同时复位,否则可能会发生CPU复位结束开始运行了,而外设还在复位中。(nRESET输入CPU复位脚)

系统分类: 单片机
用户分类: 学习设计
标签: 无标签
来源: 无分类
发表评论 阅读全文(695) | 回复(0)

0

关于投票
使用无源232-485转换器的通信不畅的问题

    一个采用485总线的项目,刚调试的时候,数据通信正常。(4个节点,485总线最远也就是300米)过了几天,再去检查发现老是通信不顺畅。开始怀疑是线的问题,检查后发现线没有问题。后来更换成为了有源隔离类型的485转换器,立刻就工作正常了。

         看来无源485转换器的通信距离还是非常有限的,当485总线比较长的时候,还是使用有源的比较好。

系统分类: 汽车电子
用户分类: 学习设计
标签: 无标签
来源: 原创
发表评论 阅读全文(698) | 回复(1)

0

关于投票
有用的设计资料

把在网上找到的有用资料记录下来。

设计中有许多共性的东西,如果有一个通用的设计就好了。比如,我需要一个9V输出的电路,电流峰值1A,平时功耗很低10mA以下,输入电源9~24V,应该如何设计这样的电源电路?可能很多方式都可以实现,到底怎么才是比较好的方案?

1,负载开关

     经常需要控制外设的电源。除了使用可以关断的电源芯片以外,还可以使用负载开关Load Switch,如FPF1004。

2,电机驱动

      常用的是L298,是一个H桥驱动芯片。今天突然在力源的网站上看到了Freescale的H桥驱动芯片,种类非常多。下次设计的时候可以采用,但是价格比较贵,也占用管脚,因为其保护做的多。

3,小电流低静态电流的芯片

       理光有好多电源芯片rx5系列是一个线形稳压电源芯片,静态功耗是几个微安,在低电流消耗的情况下,可以使用。

4,电源选择

        有个产品耗电不多,大约在几个mA,开始选择的芯片是LM2595S,稳压到9V。结果发现效率太低。后来修改位LM317。今天又发现了一个芯片LT1934芯片,静态功耗大约12uA,输入电压最大到34V,电流也可以是几百mA,如果选这个比最初的LM2595S要好。有个项目中需要用到12V蓄电池转换为9V供电,想用LM317,发现静态功耗大约6mA,然后换成1117ADJ,功耗在9mA左右,静态功耗都太大了。决定采用r1224n这个开关电源芯片(实际测试了一下,用12V供电,9V输出,静态功耗为0.8mA)。LM2595S系列的静态功耗也很大,并且在小电流的时候效率也很低,可能这种标注了多少A电路的集成DCDC都是在额定电流附近才能达到最高效率。

系统分类: 嵌入式
用户分类: 学习设计
标签: 无标签
来源: 原创
发表评论 阅读全文(323) | 回复(0)

0

关于投票
上传一个以前写的学习笔记

一个有关NXP的LPC900系列单片机的ISP应用的应用笔记。

pdf

一个有关EEPROM读写的应用笔记。包括模拟IIC和硬件IIC对EEPROM进行读写。

pdf

一个有关时钟芯片DS1302和AVR单片机接口的应用笔记。

pdf

系统分类: 嵌入式
用户分类: 学习设计
标签: 无标签
来源: 原创
发表评论 阅读全文(455) | 回复(1)

0

关于投票
机器人手拉车的原理

        前一段时间看了一段叫做“机器人老爹”的视频。讲的是北京通州一个农民做机器人的故事。看到那么多活蹦乱跳的机器人,真是让人叹为观止。真真是世上无难事,只要肯攀登。

点击看大图

        想自己也做一个机器人手拉车玩玩。当然第一步是弄懂原理。首先看了几遍录像,不能看出原理来。只好去知识产权局的网站上去搜。发现了两篇比较贴切的专利,分别是:双足步行拉车机器人和 可行走模型人拉车装置。

         仔细分析,该机器人有两个关键技术点:行走和拐弯。

         行走

         从两篇专利都可以看出,行走的原理是一致的:采用平行四边形连杆机构。驱动其中的一个连杆,带动四个连杆一起运动。驱动采用的是曲轴,电机带动曲轴转动,跟曲轴相连的连杆做往复运动,最终带动平行四边形机构运动。

 点击看大图

       转弯          

       技术关键点2是转弯。一种方式是采用车轮转向的原理。这种方式跟普通的汽车的转向方式类似。由方向盘带动转向杆拨动两个轮子同时转动。

         但是,转向部分还是不能肯定是否用的这种方式,是否有其他更好的方式?如果大家知道不妨给我留言。
系统分类: 自由话题
用户分类: 学习设计
标签: