لقد طرحت مواضيع كثيرة عن الفولتميتر في هذا المنتدى وأغلبها بلغة المايكروسي .
لكني أجد أن الكود الذي قدمه
المهندس/ احمد عبد الكريم مراد هو أكثر تلك الأكواد تميزاً واحترافاً .
وأريد التعليق على أهم ما أعجبني في الكود :
1- استخدام تلك الطريقة الرائعة في تحويل الأرقام إلى ASCII Code وذلك بإضافة الرقم 48 إلى الرقم المراد عرضه على الشاشة .
فمثلا الرقم صفر لكي تعرضه على الشاشة لابد أن تكتبه بالاسكي كود . والأسكي كود الخاص بالرقم صفر هو 48 .
والرقم واحد الأسكي كود له هو 49
والرقم اثنين الاسكي كود له هو 50
...
..
وهكذا
إذن نلاحظ أن أي رقم من 0 إلى 9 يمكننا تحويله إلى الأسكي كود بإضافة 48 وبعد ذلك يتنسى لنا بسهولة عرضه على الشاشة .
وهكذا فعل المهندس أحمد مراد أكرمه الله حيث كتب
هناك الكثيرين لا يستخدمون هذه الطريقة الجميلة ويستخدموا دوال جاهزة في المايكروسي تقوم بتحويل الرقم إلى مصفوفة بها عناصر كل عنصر عبارة عن رقم مكتوب بالاسكي كود .. هذه الدوال مثل :
ByteToStr
ShortToStr
WordToStr
IntToStr
LongToStr
FloatToStr
ثم بعد ذلك تظهر لهم مشكلة وجود عناصر في هذه المصفوفة عبارة عن فراغات فيكتبوا كود يقوم بمسح هذه الفراغات لكي تظهر الأرقام بجوار بعضها البعض
واستخدم تلك الطريقة المؤلف dogan ibrahim في كتابه advanced pic microcontroller projects
عندما كان يقدم مشروع الفولتميتر وهذا هو الكود الذي كتبه ذلك المؤلف القدير
كود:
void main()
{
unsigned long Vin, mV;
unsigned char op[12];
unsigned char i,j,lcd[5];
TRISC = 0; // PORTC are outputs (LCD)
TRISA = 0xFF; // PORTA is input
//
// Configure LCD
//
Lcd_Init(&PORTC); // LCD is connected to PORTC
Lcd_Cmd(LCD_CLEAR);
Lcd_Out(1,1,"VOLTMETER");
Delay_ms(2000);
// Configure A/D converter. AN0 is used in this project
//
ADCON1 = 0x80; // Use AN0 and Vref=+5V
//
// Program loop
//
for(;;) // Endless loop
{
Lcd_Cmd(LCD_CLEAR);
Vin = Adc_Read(0); // Read from channel 0 (AN0)
Lcd_Out(1,1,"mV = "); // Display "mV = "
mV = (Vin * 5000) >> 10; // mv = Vin x 5000 / 1024
LongToStr(mV,op); // Convert to string in "op"
//
// Remove leading blanks
//
j=0;
for(i=0;i<=11;i++)
{
if(op[i] != ' ') // If a blank
{
lcd[j]=op[i];
j++;
}
}
//
// Display result on LCD
//
Lcd_Out(1,6,lcd); // Output to LCD
Delay_ms(1000); // Wait 1 second
}
}
وهذه الطريقة ممتازة أيضاً وتتميز بأنها تعطي الرقم كله احاد وعشرات ومئات و... وتضعه في مصفوفة يمكنك أن تعرض محتويات هذه المصفوفة مباشرة دون أن تعرض حرف حرف .. وهذا هو الفارق بينها وبين طريقة المهندس أحمد عبد الكريم
أي أن أهم فارق بين الطريقتين أن أحدهما تحول حرف حرف والأخرى تقوم بتحويل الرقم كاملاً .
============================
2- الشيء الثاني الذي أعجبني كثيراً في الكود هو أن المهندس أحمد استخدم العلامة العشرية وعرض بعدها ثلاثة أرقام وذلك من خلال فكرة رائعة أيضاً
فقام أولاً بقسمة الناتج على ألف ووضع ناتج القسمة على الشاشة بالطبع مع تحويل الناتج للأسكي كود
كود:
ch = tlong / 1000; // Extract volts (thousands of millivolts)
// from result
Lcd_Chr(2,9,48+ch); // Write result in ASCII format
ثم أظهر العلامة العشرية على الشاشة
سيكون هناك ثلاث أرقام بعد العلامة العشرية .
فإذا اعتبرنا أن أول رقم بعد العلامة هو المئات وثاني رقم العشرات وثالث رقم الآحاد
فهنا قام المهندس احمد بطريقة جميلة لاستخراج المئات بمفردها وعرضها على الشاشة ثم قام باستخراج العشرات بمفردها من الرقم وعرضها على الشاشة ثم قام باستخراج الآحاد بمفردها وعرضها على الشاشة
وذلك من خلال الكود التالي
كود:
ch = (tlong / 100) % 10; // Extract hundreds of millivolts
Lcd_Chr_CP(48+ch); // Write result in ASCII format
ch = (tlong / 10) % 10; // Extract tens of millivolts
Lcd_Chr_CP(48+ch); // Write result in ASCII format
ch = tlong % 10; // Extract digits for millivolts
Lcd_Chr_CP(48+ch); // Write result in ASCII format
============================
3-
في الكود السابق المستخدم لعرض الأرقام بعد العلامة العشرية تلاحظ استخدام المتغير ch عدة مرات بدلا من استخدام عدة متغيرات وهذا توفير في ذاكرة البك .. ويدل على المهارة البرمجية
ويمكنك ملاحظة ذلك أيضا عندما كتب
كود:
tlong = tlong / 1023;
============================
بصراحة أخي المهندس احمد ,, الكود كله جميل ولكن النقاط الثلاث السابقة هي التي أعجبتني كثيرا لذلك حاولت أن أضع هذه التلميحات البسيطة عليها لكي تعم الفائدة ...
أكرمك الله وسدد خطاك و إنه لشيء جميل أن ينضم لهذا المنتدى أشخاص متميزين مثلك .
وهذا هو الكود إخواني لمن لم يقم بتحميله
كود:
// LCD module connections
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_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 TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_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 connections
int adc;
unsigned char ch;
long tlong;
char *text;
char *text1;
void main() {
LCD_INIT();
LCD_CMD(_LCD_CURSOR_OFF); // disable Cursor
ADCON1=0b00000001;
TRISA=0xFF;
TRISB=0x00;
TRISC=0x00;
text1="Sheimy Voltmater";
text="Voltage :";
while(1){
adc= ADC_Read(2); // A/D conversion. Pin RA2 is an input.
LCD_OUT(1,3,text1);
Lcd_Out(2,1,text); // Write result in the second line
tlong = (long)adc * 5000; // Convert the result in millivolts
tlong = tlong / 1023; // 0..1023 -> 0-5000mV
ch = tlong / 1000; // Extract volts (thousands of millivolts)
// from result
Lcd_Chr(2,9,48+ch); // Write result in ASCII format
Lcd_Chr_CP('.');
ch = (tlong / 100) % 10; // Extract hundreds of millivolts
Lcd_Chr_CP(48+ch); // Write result in ASCII format
ch = (tlong / 10) % 10; // Extract tens of millivolts
Lcd_Chr_CP(48+ch); // Write result in ASCII format
ch = tlong % 10; // Extract digits for millivolts
Lcd_Chr_CP(48+ch); // Write result in ASCII format
Lcd_Chr_CP('V');
Delay_ms(1000);
}
}
==========================
عتاب بسيط على من رأى الموضوع وشاهد الكود : وهو أين الأسئلة ؟؟...!! أم أن الكل فهم الكود تماماً .. صدق من قال : العلم لا يأتي لمستحي ولا لمستكبر .
===================================
وفقنا الله جميعا لما يحب ويرضى ورزقنا وإياكم العلم النافع والعمل الصالح
والسلام عليكم ورحمة الله وبركاته