 |
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
|
|
نشاط [ F.Abdelaziz ]
قوة السمعة:333
|
|
07-07-2017, 11:44 AM
المشاركة 3
|
|
تدريب : توصيل أجهزة متعددة على متن ناقل I2C مشترك :
الدائرة الكهربية :

يوجد 2 ذاكرة EEPROM تسلسلية نوع 24LC512 و مستشعر لدرجة الحرارة DS1631 متصلة على ناقل I2C مشترك . يتم تجنب الصراع conflict بين شريحتى الذاكرة EEPROMs بتوصيل الطرف A0 لأحدهما بالأرضى والطرف A0 للثانى بالجهد Vcc . العناوين ذات السبع بتات للثلاثة أجهزة مبينة بالشكل . المقاومتين 10K هى مقاومات السحب لأعلى لخطى الناقل I2C . خط البيانات SDA وخط الساعة SCL متصلان بالأطراف RB0 و RB1 للميكروكونترولر PIC18F2550 على الترتيب .
كما يتم توصيل وحدة عرض LCD لعرض عمليات القراءة والكتابة على الناقل I2C .
البرنامج :
سوف نكتب برنامج لاختبار الاتصال بالناقل I2C بين الميكروكونترولر PIC18F2550 والثلاثة أجهزة المتصلة بالناقل المشترك . سوف يقوم البرنامح أولا بالتحقق (اختبار) من وجود جميع الأجهزة الثلاثة على الناقل ، ثم يرسل أمر تحويل درجة الحرارة إلى الجهاز DS1631 . عندئذ يتم قراءة درجة الحرارة فى شكل 2 بايت وتخزينها فى شريحتى الذاكرة
( البايت المرتفع فى شريحة EEPROM الأولى والبايت المنخفض فى شريحة EEPROM الثانية ، بدءا من الموقع صفر ). بعد تسجيل خمس عينات ، يتم قراءتها بشكل تسلسلى من مواقع ذاكرة EEPROM ، وتحويلها إلى وحدات درجة حرارة فعلية (°C) وعرضها على شاشة وحدة العرض LCD .
فى برنامجنا ، سوف يقوم PIC18F2550 أولا بالتحقق من تواجد (إتاحة) الثلاثة أجهزة على الناقل . يتم ذلك بإرسال عنوان الجهاز لكل منهم فإذا تسلمه ، فهذا يعنى أنه موجود . دالة (روتين) الميكروسى للتحقق من وجود الجهاز على الناقل I2C كما يلى :
كود:
void check_device(unsigned short dev_address){
I2C1_Start();
if (I2C1_Wr(dev_address)){ //I2C1_Wr Returns 0 if there were no errors.
Lcd_Out(2,1,"Device not found");
}
else Lcd_Out(2,1,"Device is OK");
I2C1_Stop();
}
جزء البرنامج التالى يسمح للميكروكونترولر PIC18F2550 بإرسال أمر "بدء تحويل درجة الحرارة"
Start Convert T إلى DS1631 ، ثم الانتظار لمدة 750 ms حتى يتم إجراء تحويل درجة الحرارة فى شكل 12-bit ، وفى النهاية يتم استقبال قراءة درجة الحرارة المكونة من 2 بايت .
كود:
// Read temperature
I2C1_Start();
I2C1_Wr(DS1631); // Send device address
I2C1_Wr(0x51); // Start Convert Temp command
I2C1_Stop();
Delay_ms(750);
I2C1_Start();
I2C1_Wr(DS1631); // DS1631 Address again , with write
I2C1_Wr(0xAA); // Read Temperature command
I2C1_Repeated_Start();
I2C1_Wr(DS1631+1); // Address with Read
MS_Byte = I2C1_Rd(1); // Read MSB and send ACK
LS_Byte = I2C1_Rd(0); // Read LSB and send NAK
I2C1_Stop();
يمكنك ملاحظة أنه عند قراءة البايت الأخير فإن PIC18F2550 ليس بحاجة لإرسال نبضة "تسلم" acknowledge.
الروتينات التالية سوف تؤدى عمليات قراءة وكتابة بايت مع شرائح الذاكرة EEPROMs .
كود:
//--------------- Reads data from 24LC512 EEPROM - single location
unsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {
unsigned short rAddrH, rAddrL, result;
rAddrH = 0;
rAddrL = rAddress;
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(EEPROM_Select); // send byte via I2C1 (device address + W)
I2C1_Wr(rAddrH); // send Higher address byte
I2C1_Wr(rAddrL); // send Lower address byte
I2C1_Repeated_Start(); // issue I2C1 signal repeated start
I2C1_Wr(EEPROM_Select+1); // send byte (device address + R)
result = I2C1_Rd(0u); // Read the data (NO acknowledge)
while (!I2C1_Is_Idle())
asm nop; // Wait for the read cycle to finish
I2C1_Stop();
return result;
}
//--------------- Writes data to 24LC512 EEPROM - single location
void EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {
unsigned short wAddrH, wAddrL;
wAddrH = 0;
wAddrL = wAddress;
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(DeviceSelect); // send control byte
I2C1_Wr(wAddrH); // send higher address byte
I2C1_Wr(wAddrL); // send lower address byte
I2C1_Wr(wData); // send data to be written
I2C1_Stop();
}
كود البرنامج :
كود:
/*
Project: Multiple I2C devices on a common bus
MCU: PIC18F2550 * 48.0 MHz (StartUSB for PIC board)
Copyright * Rajendra Bhatt
May 6, 2011
*/
// Define LCD module connections.
sbit LCD_RS at RC6_bit;
sbit LCD_EN at RC7_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISC6_bit;
sbit LCD_EN_Direction at TRISC7_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connection definition
void Delay2s(){
Delay_ms(2000);
}
void check_device(unsigned short dev_address){
I2C1_Start();
if (I2C1_Wr(dev_address)){
Lcd_Out(2,1,"Device not found");
}
else Lcd_Out(2,1,"Device is OK");
I2C1_Stop();
}
//--------------- Writes data to 24LC512 EEPROM - single location
void EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {
unsigned short wAddrH, wAddrL;
wAddrH = 0;
wAddrL = wAddress;
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(DeviceSelect); // send control byte
I2C1_Wr(wAddrH); // send higher address byte
I2C1_Wr(wAddrL); // send lower address byte
I2C1_Wr(wData); // send data (data to be written)
I2C1_Stop();
}
//--------------- Reads data from 24LC512 EEPROM - single location
unsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {
unsigned short rAddrH, rAddrL, result;
rAddrH = 0;
rAddrL = rAddress;
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(EEPROM_Select); // send byte via I2C1 (device address + W)
I2C1_Wr(rAddrH); // send Higher address byte
I2C1_Wr(rAddrL); // send Lower address byte
I2C1_Repeated_Start(); // issue I2C1 signal repeated start
I2C1_Wr(EEPROM_Select+1); // send byte (device address + R)
result = I2C1_Rd(0u); // Read the data (NO acknowledge)
while (!I2C1_Is_Idle())
asm nop; // Wait for the read cycle to finish
I2C1_Stop();
return result;
}
char message1[] = "I2C Devices ";
char message2[] = "with PIC18F2550" ;
char Sample[] = "Sample 0";
char temp[] = "00.0000 C";
unsigned int address, Fraction_Temp;
unsigned short i,MS_Byte, LS_Byte, Whole_Temp;
const int EEPROM1 = 0xA0, EEPROM2 = 0xA2, DS1631 = 0x90;
void main() {
CMCON = 0x07; // Disable comparators
ADCON1 = 0x0F; // Disable Analog functions
TRISC = 0x00;
TRISB = 0x00;
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // CLEAR display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,1,message1); // Write message1 in 1st row
Lcd_Out(2,1,message2); // Write message1 in 1st row
Delay2s();
I2C1_Init(100000); // Initiate I2C
// Check EEPROM1
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"EEPROM1");
check_device(EEPROM1);
Delay2s();
// Check EEPROM2
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"EEPROM2");
check_device(EEPROM2);
Delay2s();
// Check Sensor
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"DS1631");
check_device(DS1631);
Delay2s();
for (i=0; i<5; i++) {
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"Reading Temp.");
// Read temperature
I2C1_Start();
I2C1_Wr(DS1631); // Send device address
I2C1_Wr(0x51); // Start Convert Temp command
I2C1_Stop();
Delay_ms(750);
I2C1_Start();
I2C1_Wr(DS1631); // DS1631 Address again
I2C1_Wr(0xAA); // Read Temperature command
I2C1_Repeated_Start();
I2C1_Wr(DS1631+1); // Address with Read
MS_Byte = I2C1_Rd(1); // Read MSB and send ACK
LS_Byte = I2C1_Rd(0); // Read LSB and send NAK
I2C1_Stop();
Delay2s();
// Write the MS Byte to EEPROM1
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"Writing MS Byte");
EEPROM_WriteByte(EEPROM1, i, MS_Byte);
Delay2s();
// Write the LS Byte to EEPROM2
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"Writing LS Byte");
EEPROM_WriteByte(EEPROM2, i, MS_Byte);
Delay2s();
}
// Reading stored temperature samples
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"Reading EEPROMs");
Delay2s();
for (i=0; i<5; i++){
Lcd_Cmd(_LCD_CLEAR);
Sample[7] = i+49; //"Sample 1","Sample 2",……,"Sample 5"
Lcd_Out(1,1,Sample);
Whole_Temp = EEPROM_ReadByte(EEPROM1, i);
Fraction_Temp = EEPROM_ReadByte(EEPROM2, i);
Fraction_Temp = Fraction_Temp >>4;
Fraction_Temp = 625*Fraction_Temp; // 12 bit resolution is 0.0625C
temp[0] = Whole_Temp/10+48;
temp[1] = Whole_Temp%10+48;
temp[3] = Fraction_Temp/1000+48;
temp[4] = (Fraction_Temp/100)%10+48;
temp[5] = (Fraction_Temp/10)%10+48;
temp[6] = Fraction_Temp%10+48;
Lcd_Out(2,5,temp);
Delay2s();
}
}
|