佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

楼主: Right

LM35D接PIC16F877A (LCD ADC)

[复制链接]
发表于 4-1-2007 11:37 AM | 显示全部楼层
原帖由 gab102001 于 3-1-2007 09:42 PM 发表


不好意思,想问问pic 大大,%2.1f 表示什么?? value output 了会有两个位数和一个小数点??
例如:26.5 degree ???

这不正是你要的吗?

%2f 表示预留2个“个位”数,显示所有的小数点。
%2.3f 表示预留2个“个位”数,显示3个小数点。
%2.1f 表示预留2个“个位”数,显示1个小数点。

自己改变看看它的分别。
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 5-1-2007 05:07 PM | 显示全部楼层
原帖由 pic 于 4-1-2007 11:37 AM 发表

这不正是你要的吗?

%2f 表示预留2个“个位”数,显示所有的小数点。
%2.3f 表示预留2个“个位”数,显示3个小数点。
%2.1f 表示预留2个“个位”数,显示1个小数点。

自己改变看看它的分别。


太好了,我明白了,又学到新东西了。。。
应该还有很多东西学吧。。。
PIC大大,真是谢谢。。。

[ 本帖最后由 Right 于 5-1-2007 05:12 PM 编辑 ]
回复

使用道具 举报

发表于 6-1-2007 12:38 PM | 显示全部楼层
原帖由 Right 于 5-1-2007 05:07 PM 发表


太好了,我明白了,又学到新东西了。。。
应该还有很多东西学吧。。。
PIC大大,真是谢谢。。。

用C就是这么简单, 会不会觉得很没有挑战性呢?
回复

使用道具 举报

发表于 6-1-2007 09:02 PM | 显示全部楼层

回复 #23 pic 的帖子

PIC 大大。。。我还想问问。。。
以下的coding里,send_nibble 代表什么???

void lcd_send_nibble( byte n )
{
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}

void lcd_send_byte( byte address, byte n )
{
      lcd.rs = 0;
      delay_ms(5);
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}
回复

使用道具 举报

发表于 7-1-2007 05:17 PM | 显示全部楼层
原帖由 gab102001 于 6-1-2007 09:02 PM 发表
PIC 大大。。。我还想问问。。。
以下的coding里,send_nibble 代表什么???

如果你有注意,LCD是有8条Data line, 但我们只接4条LCD的Data Pin,连接到PIC MCU 的D4~D7。
这是为了要省I/O line的作法,叫做4bit mode,如果你看LCD的DataSheet就知道。
但一个byte是8bit, 我们的hardware只有4bit, 就需要送两次, 那就是Upper 4bit 一次, 和Lower 4bit一次。
Send Nibble 这个Routine就是帮你做这个工作。
lcd_send_nibble(n >> 4); // Send upper 4 bit
lcd_send_nibble(n & 0xf); // Send Lower 4 bit

明白了吗?

参考:


[ 本帖最后由 pic 于 21-1-2009 07:34 PM 编辑 ]
回复

使用道具 举报

发表于 7-1-2007 07:50 PM | 显示全部楼层

回复 #25 pic 的帖子

明鸟。。。。谢谢PIC大大。。。
回复

使用道具 举报

Follow Us
 楼主| 发表于 19-1-2007 09:57 PM | 显示全部楼层
PIC大大,我看了那全部source code。。。
我也看了LCD的data sheet,有很多不同的方法启动那LCD。。。
我觉得你的source code是这样启动LCD的。。。
0x28是function set
0xc是Display on off control
1是clear display
6是entry mode set

但为什么一开始就send了两次byte 3和三次byte 2?
然后是怎样让LCD分辨display第一排和第二排?

我也看了几次CA3162的data sheet。发现你所谓的Driver timing是high speed mode,大约0.5us。而AT89C4051的timing只有几us罢了。所以AT89C4051是很难捕捉到CA3162的MSB和BCD output。就是因为CA3162的timing太快,所以temperature reading一直在快速的变。
我这样的说法对吗?

[ 本帖最后由 Right 于 19-1-2007 11:07 PM 编辑 ]
回复

使用道具 举报

发表于 20-1-2007 08:28 AM | 显示全部楼层

回复 #27 Right 的帖子

PIC大大,我看了那全部source code。。。
我也看了LCD的data sheet,有很多不同的方法启动那LCD。。。
我觉得你的source code是这样启动LCD的。。。
0x28是function set
0xc是Display on off control
1是clear display
6是entry mode set

以上是必要的initialize 过程。

但为什么一开始就send了两次byte 3和三次byte 2?

那LCD routine不是我写的, 那是Compiler 的LCD driver。
byte 3和byte 2,那是Display & Cursor home 指令, 你也可以拿掉它, 看看有什么影响。
Send几次,可能是要加强对各厂LCD的相容性,有些LCD在上电时,需要一些时间才stable。
所以send几次, 万无一失, 实际情形,我不知道。
注:Display & Cursor home 的Execution time 是40uS~1.6ms

然后是怎样让LCD分辨display第一排和第二排?

是用Set Display Address command.
lcd_gotoxy(x,y);  



我也看了几次CA3162的data sheet。发现你所谓的Driver timing是high speed mode,大约0.5us。而AT89C4051的timing只有几us罢了。所以AT89C4051是很难捕捉到CA3162的MSB和BCD output。
我这样的说法对吗?

high speed mode?大约0.5us? 是这样的吗? 这我没留意。
只是, CA3162的output是4bit BCD,3个digits,本来的设计是要Multiplex输出到3个7 Segment Display,因为是Mutiplexing, 为免7Segment Flickering 闪烁,Multiplex的Timing要很快,较难捕捉, 所以并不适合interface到MCU。

其实, MCU的速度是够快的, 但要有一些编程的技巧,但是初学者应该避免使用这种“另类”的ADC。
也不知道那网站的作者为什么用CA3162, 可能是他手斗上刚好有, 就顺便拿来用吧。。。
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 12-3-2007 01:35 AM | 显示全部楼层
谢谢PIC大大的指导。。。
虽然FYP完了,但是我还有一个疑问。。。

我看了LCD上dislay的温度,然后直接用multimeter量LM35D的output,发现温度和LM35D的output voltage不吻合,大概差1度左右。

我觉得是ADC的gain(0.48828)不对了或output voltage过了ADC后除了问题。哪我直接换它的gain,这样做对吗?
回复

使用道具 举报

发表于 13-3-2007 06:52 PM | 显示全部楼层
原帖由 Right 于 12-3-2007 01:35 AM 发表
我看了LCD上dislay的温度,然后直接用multimeter量LM35D的output,发现温度和LM35D的output voltage不吻合,大概差1度左右。

我觉得是ADC的gain(0.48828)不对了或output voltage过了ADC后除了问题。哪我直接换它的gain,这样做对吗?

差1度。。。太多了。。。

你可以Calibrate ,你的Reference voltage, VCC要稳, 才不会跑太多。
回复

使用道具 举报

 楼主| 发表于 13-3-2007 07:45 PM | 显示全部楼层
原帖由 pic 于 13-3-2007 06:52 PM 发表

差1度。。。太多了。。。

你可以Calibrate ,你的Reference voltage, VCC要稳, 才不会跑太多。


这样我想应该是Power Supply的问题。。。
因为它的supply voltage不稳定。。。
我用multimeter量了,不稳定。。。
可能是那个Power Supply的品质没那么好吧。。。
回复

使用道具 举报

发表于 31-8-2007 05:47 PM | 显示全部楼层
原帖由 pic 于 30-12-2006 12:06 PM 发表

错了 , 不是这样搞的。。。
当setup_port_a( ALL_ANALOG );, 那 ADC 的参考电压(Reference Voltage)是5V。(有需要我在说清楚)

#device ADC=10 是说用10bit ADC, 也就是 0-1023 step。
那么
如25degC, 那LM35的输出是 25x 10mV=250mV=0.25V

5V = ADC 1024
0.25V= (0.25x1024)/ 5=  ADC 51

当你得到ADC 54, 就是说  (54x 5V)/1024= 0.2636V,
换去DegC,0.2636V X 10mV/degC =26.36degC。
...


PIC版主,你好!
我有很多问题想请教你,也是关于temperature sensor的,
是我这个sem的assignment,
有用AT89S51,LM35,LM358,ADC0804(8-bit output)和两个Dual 7-segment display。。。
还要用Assembly Language写。。。

我想问说,你之前说的参考电压(Reference Voltage)=5V,这5v是pin9的Vref/2是吗?
我的lecturer给的schematic,pin9是not connect的喔!是不是一定要接去5v?

还有LM35的datasheet写着temperature range是-55c到150c,
还是这-55c到150c只是说LM35可以承受的range?而真正LM35只是sense 0c到100c?
那么那个10mv/deg还是照着你的方法去算吗?
比如:25c x 10mv = 0.25v
      0.25v/5v x 256 = ADC 12.8 decimal = D hex (对吗?)
      请问ADC的output是Hexadecimal还是decimal的?
还有,LM35的output是接去LM358 amplifier的,然后才接去ADC0804的。。。
那么是不是上面的都算错了?
是不是应该这样算,
  25c x 10mv = 0.25v(LM35)= Vin
  Vin x(1+16k/3.9k)= 1.275v(LM358)= V+
  然后才  V+ /5v x 256 = ADC 65.28 decimal = 41H
  对吗?

还有,请问ADC的output怎样send fraction去microcontroller?
是不是说100c根本没有用完255个step,
比如 max 100c => ADC  51 decimal = 33H = 0011 0011 B
前面两个0都没有用到,所以可以shift两个位,变成 1100 1100,后面两个位是fraction。。。好像错了
还是说34H到FFH都可以用来做其他的东西?

请帮帮我,我的头好大
回复

使用道具 举报

发表于 1-9-2007 09:50 AM | 显示全部楼层

回复 #32 sadsack 的帖子

回覆前,可以先看你的电路图吗?
回复

使用道具 举报

发表于 1-9-2007 01:03 PM | 显示全部楼层
原帖由 pic 于 1-9-2007 09:50 AM 发表
回覆前,可以先看你的电路图吗?


不好意思,因为schematic是lecturer的,我不知道可以放在这里吗。。。
我已经短消息给你了 。。。谢谢!
如果可以放的话,我再放上来
回复

使用道具 举报

发表于 1-9-2007 04:12 PM | 显示全部楼层
原帖由 sadsack 于 1-9-2007 01:03 PM 发表


不好意思,因为schematic是lecturer的,我不知道可以放在这里吗。。。
我已经短消息给你了 。。。谢谢!
如果可以放的话,我再放上来


ecp2036??
这时候应该是差不多是时候要交了吧。
回复

使用道具 举报

发表于 1-9-2007 04:25 PM | 显示全部楼层
原帖由 fritlizt 于 1-9-2007 04:12 PM 发表


ecp2036??
这时候应该是差不多是时候要交了吧。


应该是week12 才交吧!
我现在只剩下program的部分烦着我,还有ADC的output。。。
去问lecturer,他又视而不见:@
你知道怎样算和做?请多多指教
回复

使用道具 举报


ADVERTISEMENT

发表于 1-9-2007 08:56 PM | 显示全部楼层
原帖由 sadsack 于 1-9-2007 01:03 PM 发表


不好意思,因为schematic是lecturer的,我不知道可以放在这里吗。。。
我已经短消息给你了 。。。谢谢!
如果可以放的话,我再放上来

看了你的图,可是很蒙。。。可以放上来啊, 你的Lecturer 也不懂那里抓来的。。。

Atmel 我不熟, 可能你可以请教fritlizt 大大(你的学长?), rothmans 大大。
回复

使用道具 举报

发表于 4-5-2008 05:27 PM | 显示全部楼层
原帖由 Right 于 28-12-2006 04:09 PM 发表


我使用了您介绍的PIC16F877A接LM35D...我改了一些您给的program...如下:

#include <16F877A.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
///////////////////////////////////////////////////////////////////////////////
// LCD Driver
///////////////////////////////////////////////////////////////////////////////
// As defined in the following structure the pin connection is as follows:
/*
LCD 16 X 2 line
PortD.0-> RS
PortD.1-> RW
PortD.2-> E
PortD.3
PortD.4-> D4
PortD.5-> D5
PortD.6-> D6
PortD.7-> D7
*/
/////////////////////////////////////////////////////////////////
// LCD Driver
struct lcd_pin_map {                 // This structure is overlayed
           boolean rs;               // on to an I/O port to gain
           boolean rw;               // access to the LCD pins.
           boolean enable;           // The bits are allocated from
           boolean unused;           // low order up.  ENABLE will
           int     data : 4;         // be pin B0.
        } lcd;
#byte lcd = 0x08                 // on to port D (at address 0x08)
byte CONST LCD_INIT_STRING[4] = {0x28, 0xc, 1, 6};

void lcd_send_nibble( byte n )
{
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}

void lcd_send_byte( byte address, byte n )
{
      lcd.rs = 0;
      delay_ms(5);
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}

void lcd_init()
{
    byte i;
    set_tris_d(0);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
    {
      lcd_send_byte(0,LCD_INIT_STRING);
    }
}

void lcd_gotoxy( byte x, byte y)
{
   byte address;
   if(y!=1)
     address=0x40;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}
void lcd_putc( char c)
{
   switch (c) {
     case '\f'   : lcd_send_byte(0,1); //delay_ms(5);
                    break;
     case '\n'   : lcd_gotoxy(1,2);          break;
     default     : lcd_send_byte(1,c);       break;
   }
}
///////////////////////////////////////////////////////////////////////////////

void main()
{
   long value;
   lcd_init();
   delay_ms(6);
   lcd_putc("\fTemperature");
   lcd_putc("\nReading");
   delay_ms(1000);
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );
   set_adc_channel( 0 );
   while(TRUE)
   {
      value = Read_ADC();
      printf(lcd_putc,"\fReading: %lu ",value);
      delay_ms(500);
   }
}

可是,今天我试了之后,LCD完全没反应,没错的话,PIC16F877A是用XT oscillator如果我们用20MHz Crystal.它的pin11,12,31,32的Vss和Vdd都接了。。

那会是什么问题呢??


hihi,"Right 兄台“
我想像您询问下,您介意让我参考下您的 delay_ms(), delay_us, delay_cycles() 的函数 (function) 吗?
想像您询问,假如你丢“10“ 到 delay_ms() 和 delay_us() ,那么你 delay 的 时间是 10milisecond 和  10microsecond (误差少许) 吗?因为有 study datasheet 的关系,我看到 datasheet 里也是有讲说,on power 15 milisecond 里,"No data should be transferred to or from the display during this time".

void lcd_init()
{
    byte i;
    set_tris_d(0);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);               //       <<=== 是真的delay 15 milisecond 吗?
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }


那么 delay_cycles() 是怎样准准如果我想 delay 两个 cycles 就两个 cycle 呢?


我是用别的 mcu, 我自己有写 delay 的 function, 用 mcu 的 timer 来做 delay, 也是满准的,但如果是用 一个 loop 来做 delay 的话行吗(当我用 60 Mhz 的情况地下)?
回复

使用道具 举报

发表于 4-5-2008 05:55 PM | 显示全部楼层
原帖由 半夜鬼 于 4-5-2008 05:27 PM 发表


hihi,"Right 兄台“
我想像您询问下,您介意让我参考下您的 delay_ms(), delay_us, delay_cycles() 的函数 (function) 吗?
想像您询问,假如你丢“10“ 到 delay_ms() 和 delay_us() ,那么你 delay 的 时间 ...


delay_ms, delay_us 和delay_cycles是compiler 内建的function.
help file里面有讲到-〉This function works by executing a precise number of instructions to cause the requested delay.  It does not use any timers.  If interrupts are enabled the time spent in an interrupt routine is not counted toward the time.

也就是说这个delay是准的。。不过当有interrupt的时候会不准。如果算到一半interrupt occur,他就停止, 直到从interrupt回来为止。
delay_cycles也是compiler自己内建的函数。
我写一个简单的delay_cycles。 再看会asm/list file.发觉他只是加入nop instruction而已。

....................      delay_cycles(6);
*
003E:  NOP
003F:  NOP
0040:  NOP
0041:  NOP
0042:  NOP
0043:  NOP

用timer来做delay是很准。 interrupt的时候还会继续算。 如果用loop就好像内建的delay_ms 函数。crystal speed不是问题。 只要你instuction execution time算得准就可以了。

[ 本帖最后由 fritlizt 于 4-5-2008 05:58 PM 编辑 ]
回复

使用道具 举报

发表于 4-5-2008 06:53 PM | 显示全部楼层
原帖由 fritlizt 于 4-5-2008 05:55 PM 发表


delay_ms, delay_us 和delay_cycles是compiler 内建的function.
help file里面有讲到-〉This function works by executing a precise number of instructions to cause the requested delay.  It does not use any timers.  If interrupts are enabled the time spent in an interrupt routine is not counted toward the time.

也就是说这个delay是准的。。不过当有interrupt的时候会不准。如果算到一半interrupt occur,他就停止, 直到从interrupt回来为止。
delay_cycles也是compiler自己内建的函数。
我写一个简单的delay_cycles。 再看会asm/list file.发觉他只是加入nop instruction而已。

....................      delay_cycles(6);
*
003E:  NOP
003F:  NOP
0040:  NOP
0041:  NOP
0042:  NOP
0043:  NOP

用timer来做delay是很准。 interrupt的时候还会继续算。 如果用loop就好像内建的delay_ms 函数。crystal speed不是问题。 只要你instuction execution time算得准就可以了。


明白,谢谢fritlizt 大大。。
不过我是用 C 来写,不知道单单一个单纯的
while(1);  //<== 需要用多少时间
or
for (i=0; i<10; i++) ; //<== 需要用多少时间

用示波器看看应该可以了。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 3-2-2025 03:48 AM , Processed in 0.129483 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表