2014年10月25日 星期六

LCD I2C模組使用.

http://www.geeetech.com/wiki/index.php/Serial_I2C_1602_16%C3%972_Character_LCD_Module
1602I2C 1.jpg 1602I2C 2.jpg
This is another great blue/yellow backlight LCD display. As the pin resources of Arduino controller is limited, your project may be not able to use normal LCD shield after connected with a certain quantity of sensors or SD card. However, with this I2C interface LCD module, you will be able to realize data display via only 2 wires. If you already has I2C devices in your project, this LCD module actually cost no more resources at all. It is fantastic for Arduino based project.

  • Interface: I2C
  • I2C Address: 0x27
  • Pin Definition : VCC、GND、SDA、SCL
  • Back lit (Green with white char color)
  • Supply voltage: 5V
  • Size : 27.7mm×42.6mm
  • Contrast Adjust : Through Potentiometer
  • Only employ two I/O interface
Here is pic shows how to connect an Arduino 1602 I2C module.The following is a table describing which pins on the Arduino should be connected to 1602 I2C LCD module.
1602I2C 4.jpg
1602I2C table.jpg
1602I2C 3.jpg
Spinnig the potentimeter clockwise is to increase contrast ,spinning unclockwise is to decrease it

Arduino 1602 I2C library only Arduino IDE 023!
Arduino 1602 I2C library for Arduino IDE 1.0   http://www.geeetech.com/Documents/LiquidCrystal_I2Cv1-1.rar
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
 lcd.init();                      // initialize the lcd 
 // Print a message to the LCD.
 lcd.backlight();
 lcd.print("Hello, world!");
}
void loop()
{
}


=========================================================
來源: 




由於最後我們的作品希望可以展示時間和各種需要顯示的狀態,因此決定安裝一塊LCD模組,不過剛剛有提到過,我們有許多各種需要顯示的東西,因此表示我們的Arduino UNO已經沒有辦法再提供豐富的腳位給我們的LCD使用。



在Cooper Maa大大中的一篇文中"Arduino 筆記 – Lab9 在 2x16 LCD 上顯示 "Hello World" 訊息",我們可以知道即使使用了最少IO port的做法,也得要有四條data線、RS暫存器選擇線和E致能線,加上電源兩條,總共就得消耗八條線路,其中六條還是用去了digital,以UNO來說,幾乎用去了大半,這樣一來我可能得再購買一塊arduino分別控制LCD和其他裝置,這是相當不方便的,不僅要花錢還得另外進行兩塊UNO的連線,否則就是要購買mega來使用。

(內心:...........但是我沒這麼多錢,而且我懶.............我就是只有一塊UNO,究竟有沒有辦法不要佔去這麼多digital腳位,又可以讓我使用需要很多腳位的LCD呢?)



碰巧被我找到這麼一塊好東西,這樣一來我連一根digital腳位都沒有消耗,搭配RTC模組使用,甚至可以說,我一根腳位都沒有浪費的使用,那就是I2C模組拉QWQ!!!!!(QWQ,這是一種網路表情符號,表示很感動的意思。)


本篇最一開始就是LCD I2C模組的圖片
http://www.geeetech.com/wiki/index.php/Serial_I2C_1602_16%C3%972_Character_LCD_Module


不過外觀看起來和一般的LCD沒什麼太多的不同,唯一有不同的就是多插了一塊小IC晶片PCF8574,他是I2C的8bits擴充IC,利用他就可以將Arduino的腳位擴充,或許將來的專題我可以使用它來做許多多腳位的裝置。

PCF8574的data sheet
http://www.datasheetcatalog.org/datasheet2/b/0fjjhr6h643gldhx3o1rgkyk7ucy.pdf

關於PCF8574有個專業的教學網站在說明這塊IC怎麼使用
http://garagelab.com/profiles/blogs/tutorial-arduino-i-o-port-expander-with-pcf8574
他還提到怎麼應用在一般的LCD上面,使一般的LCD也變成I2C的LCD模組
http://garagelab.com/profiles/blogs/tutorial-lcd-using-only-2-arduino-pins-with-pcf8574-and-i2c


接下來這邊來說說實作方式


在剛剛的網站裡面有下載檔案,我將下載網址連過來。
http://www.geeetech.com/wiki/index.php/Serial_I2C_1602_16%C3%972_Character_LCD_Module

總共分成0023和1.0版本可以使用
Arduino IDE 023
Arduino IDE 1.0


開啟之後可以稍微看看範例檔案,下列的程式我有稍微修改過。

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
// 0x27是LCD模組的地址,16表示有十六欄位,2表示總共有2欄
LiquidCrystal_I2C lcd(0x27,16,2);  
void setup()
{
    //LCD初始化
    lcd.init();   
    lcd.init();
    //開啟背光
    lcd.backlight();
    //清除先前畫面
    lcd.clear();
    //設定第一個字顯示座標
    lcd.setCursor(0,0);
    //顯示字串
    lcd.print("Hello, world!");
}
void loop()
{
}

在導入.h檔和定義好LCD I2C之後,在setup那邊需要初始化LCD和開啟背板光源,之後只要設定座標和使用lcd.print即可顯示我們想要顯示的資料,用起來實在是相當的方便,以後只要Serial.print可以顯示,LCD上面一樣可以顯示。

舉例來說,我將Arduino的第一個基礎範例analogReadSerial來進行修改。

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
void setup() {
  Serial.begin(9600);
  lcd.init();   // initialize the lcd 
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.clear();
}

void loop() {
  int sensorValue = analogRead(A0);
  lcd.setCursor(0,0);
  lcd.println(sensorValue, DEC);
}

我將該設定的部分設定好之後,把Serial.println換成lcd.print即可顯示。

這東西實在是太方便了~~~~

不過雖然Arduino的模組們用起來很方便,但是等到會用了之後,還是建議大家回到最初使用LCD的方式玩看看,才能夠真正的了解為什麼可以用兩隻腳就可以操控LCD是一件多麼讓人感動的事情,而且也可以同時了解四位元和八位元的意義是什麼,這樣回過頭來去尋找源頭的過程中,就像是考古學家一樣,會發現許多前人留下的有趣故事唷。

2014年10月19日 星期日

单片机数据通信之单总线数据传输分析

http://www.ednchina.com/ART_8800519406_29_35572_TA_d82944e3.HTM?click_from=8800024069,9950021346,2014-10-18,EDNCOL,NEWSLETTER


单片机数据通信之单总线数据传输分析

作者: / 上网日期: 2014年10月16日  评论[ 0 ]  
分享到:  新浪微博   qq空间   qq微博   人人网   百度搜藏  
  字号: 
关键字:单片机   控制器   数据通信  
单片机干不了大事,必须得配上各种外设,那么了解单片机与传感器之间的数据通信就显得必不可少了。常见的单片机数据通信方式有SPI,IIC,RS232,单总线等等。每种通信方式都有相应的时序图,分析时序图并完成代码的编写是单片机学习者的必修课。本文以DS18B20为例分析一下单总线数据传输。
DS18B20是单总线数据传输,因此对于时序的要求就非常的高,学会分析其时序图是非常有必要的。
例说单片机数据通信之单总线数据传输
1.初始化时序图分析:
例说单片机数据通信之单总线数据传输
首先是由总线控制器拉低总线,维持480us。在480us后释放总线,由上拉电阻讲总线拉高。等待5-60us后,DS18B20开始响应,会将数据总线拉低60-240us.之后便释放总线,由上拉电阻拉高总线。转换为代码如下:
u8 dsbInit() //初始化,返回0表示DS18B20无反应,反之有响应
{
dsbDQStat(0); //控制器拉低总线
delay500us(); //拉低总线一段时间
dsbDQStat(1); //释放总线
delay60us(); //等待DS18B20响应
if(dsb_DQ) //如果没有相应直接返回0
{
return 0;
}
delay240us(); //有响应则等待响应结束
return 1; //返回初始化状态
}
2.读时序图分析:
例说单片机数据通信之单总线数据传输
首先由控制器将总线拉低>1us的时间,此时控制器释放总线,如果此时控制器采样为低电平,那么读到的值便是0,如果为高电平,则读到的值为1。注意图中标有一个15us,其意思便是控制器采样在15us内完成。15us后是由上拉电阻将总线拉高维持45us。整个读周期为15+45=60us。这个周期的时间也是得控制的。转换为代码如下:
u8 dsbReadByte() //读出一个字节的数据,从低位开始读取
{
u8 i,tmp = 0;
for(i = 0;i < 8;i++)
{
dsbDQStat(0); //控制器拉低总线
tmp >>= 1; //低位开始读
dsbDQStat(1); //释放总线
if(dsb_DQ) tmp |= 0x80;
delay15us();
delay45us(); //控制周期时间
}
return tmp;
}
3.写时序图分析:
例说单片机数据通信之单总线数据传输
首先由控制器拉低总线15us,之后,如果要写入0,则继续拉低总线并为此45us.如果要写入1则释放总线由上拉电阻拉高总线,也为此45us。写时序相对比较简单,转换为代码如下:
void dsbWriteByte(u8 dat)//写一个字节的数据,从低位开始
{
u8 i;
for(i = 0;i < 8;i++)
{
dsbDQStat(0); //控制器拉低总线
delay15us(); //维持15us
if(dat & 0x01) dsbDQStat(1);
else dsbDQStat(0);
dat >>= 1;
delay45us();
dsbDQStat(1); //45us后释放总线
}
}
DS18B20的三个时序图就分析完了,DS18B20只是单总线数据通信中的一个例子,大家了解了DS18B20时序图的分析,那么就可以试试分析DHT11的时序图完成其初始化函数,以及读数据函数。

淺談 PLL - 鎖相環(PLL: Phase-locked loops)

淺談 PLL - 鎖相環(PLL: Phase-locked loops)
以下為小弟個人的理解方式來討論:
很多人還依然對 PWM 或是 OPA 或 BJT 依然茫然,
是因為在純軟體設計上很少會接觸到實際電路的問題,
小弟本身對許多軟體也是不了解的多...
而相鎖部份小弟希望用軟體的角度去說明這個技術,
由維基找到的資料我們可以在圖中看到幾個區塊:
鑑頻鑑相器
低通濾波器
壓控振盪器
反饋迴路
而透過程式中的部份呢 P 相位 L 鎖定 L 迴圈 <= 第三個最簡單我們先用程式寫下
while (1) <= L 迴圈完成 
而相位鎖定部份先解說與舉例其原理和用途,
PLL 在實際上電路產品的運用範圍很廣範,比如電視的 TUNER
選台器,而選台器是一種什麼樣的設計和原理?!
如果你已經具備了如超外差接收器的觀念,對於 IF 中頻、本振等等部份已經了解,那麼... 很棒,但是我會用更簡單的方式說明,
一個影像是由 6MB 的頻寬所組成:
這裡面包括了 3.58 MHZ 的色載波訊號,也被稱為繫色訊號,
以及 1 MHZ 的音頻訊號,調變訊號,
而傳輸這 6MB 的訊號是由 數十MB到上GHZ 的載波訊號來傳輸,而我們所說的 TUNER 正是解這個載波訊號部份,而取的 6MB 我們要的影音資料,
因此 PLL 也就是用在這部份,TUNER 的原理是產生出一個本振頻然後去跟載波混合,然後會產生出一個 IF 中頻,然後做中頻放在再解出訊號資料,過去中放是很難做的一種技術,而載波頻率太高並且訊號非常微弱,可能是 -90DB 以下,所以把訊號降到中頻率後再放大到幾十萬倍,就可以進行處理了,所以 TUNER 的主要功能是把一本地振盪訊號,和外來訊號加到混波器中,會出現 A+B 和 A-B 及 A 與 B 四種訊號,IF 中頻訊號即是 A-B 訊號,
而這裡我們會用到相鎖環,當我們產生出的本振訊號過高或是過低於某一頻率的載波時,TUNER 裡面的鎖定訊號就會沒抓到,那我們就進行微調將頻率上一點或是下一點,所以 LOCK 鎖定部份我們需要一個判斷式來幫忙,IF( detect(LOCK) ) <= 這部份就產生了,所以我們把式子加到一起去變成:
while(1)
{
if ( detect(LOCK) )
}
但是我們不知道要往上調是鎖住還是往下調才能鎖住?!
假定我們先將一個數值範圍給設定住,比如頻率部份只能夠用2個BYTE去控制,第一個BYTE是粗調整後一個BYTE是細調整,而我們所要找到的載波是 55.25 MHZ 第 1 臺的位置,那麼可能我們在粗調整部份已經找到是 10 的值給進去,細調整部分我們則給 255 或是 0,然後一直往上調上去,一直到鎖定訊號後完成,再往上追 15 個或是 20 個值再往下調整到鎖定,把下範圍與上範圍的值加起來除 2,得到中央值,
那我們可以這樣完成式子:
int val_up, val_down, val_lock;
while(1)
{
lock_val--;
if ( detect(val_lock) )
break;
}
val_up=val_lock;
val_lock-=20;
while(1)
{
lock_val++;
if ( detect(val_lock) )
break;
}
val_down=val_lock;
val_lock=(val_up+val_down)/2;
最後我們得到一個 val_lock 值,是我們所需要的,
在以上的範例中並不是 PLL 的實際應用,而是調頻器的應用,
但是程式的部份是相同以及觀念部份是相同的,而把頻率改為相位,
超前或是落後,就是 PLL 的實際應用,
DRAM 的頻率調整也類似這樣的方式,程式中的 P 相位我們可以看成是 DETECT() 而 L 鎖定則是 IF( DETECT(LOCK) ) 最後環 L 就是 WHILE(1)
是有點奇怪啦... 總之... 就醬子~