[Help] Đọc ADC và hiện số thực trên LCD

lee_trieu

Gà con
Chào mọi người !! Em đang có một vướn mắc chỗ đọc ADC hiện lên LCD mong mọi người giúp đỡ ạ:-(
Vấn đề em vướn phải là hiện số thực lên LCD(Em dùng thư viện LCD của Câu lạc bộ):5cool_sweat:
Nhìn mạch dưới thì như mọi người thấy đó 3.10V nhưng nó lại làm tròn thành 3.00V
Em thử ép kiểu sang số thực nhưng không được:-s.


Em viết code thế này:
PHP:
#include <msp430g2553.h>
#include "conf_lcd.c"
int dienthe;
 
int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled
  ADC10CTL1 = INCH_1 + CONSEQ_2;                      // input A1
  ADC10AE0 |= 0x02;                         // PA.1 ADC option select
  P2DIR |= 0x01;   
  
  conf_lcd(0);
  lcd_clear();
  for (;;)
  {  
   dienthe= ((ADC10MEM*5)/1023)*100;
  // dienthe=float(dienthe);
   ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
   // __bis_SR_register( CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit
    lcd_gotoxy(0,0);
    lcd_puts("Dien Ap:");
    lcd_gotoxy(0,1);  
    lcd_number(dienthe,2,0);
    lcd_gotoxy(4,1);  
    lcd_putc('V');
  }
}
em thử sửa chỗ:
Code:
   dienthe= ((ADC10MEM*5)/1023)*100;
và
   lcd_number(dienthe,2,0);
Thành
Code:
dienthe= ((ADC10MEM*5*10)/1023);
và
 lcd_number(dienthe,1,0);
Thì 3.18V nó hiện ra 3.1V:-slink project của em:
https://dl.dropboxusercontent.com/u/23155150/ADC And LCD.rar
 

mafiaWolf

Chủ tịch Hội phụ nữ PIF
Nếu 3.18v mà hiện 3.1v thì theo mình nghĩ cái hàm lcd_number(dienthe,1,0) bạn nên giữ nguyên là lcd_number(dienthe,2,0) cho nó lấy 2 số sau dấu phẩy ^^ không biết phải không..Cơ mà ở trên thì nhân 100 mà sao sửa lại chỉ còn nhân 10 vậy @@
 

lee_trieu

Gà con
Nếu 3.18v mà hiện 3.1v thì theo mình nghĩ cái hàm lcd_number(dienthe,1,0) bạn nên giữ nguyên là lcd_number(dienthe,2,0) cho nó lấy 2 số sau dấu phẩy ^^ không biết phải không..Cơ mà ở trên thì nhân 100 mà sao sửa lại chỉ còn nhân 10 vậy @@
Nếu mình để
Code:
 lcd_number(dienthe,2,0)
thì nó ra 0.31V chứ không phải 3.18V:5cool_sweat:
 
H

huunho

Guest
bạn sửa chương trình main.c như sau là ok ngay nhé:


int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled
ADC10CTL1 = INCH_1 + CONSEQ_2; // input A1
ADC10AE0 |= 0x02; // PA.1 ADC option select
P2DIR |= 0x01;

conf_lcd(0);
lcd_clear();
for (;;)
{

dienthe= (((ADC10MEM*49)/100));

//dienthe=float(dienthe);
//dienthe= d;
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
// __bis_SR_register( CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
lcd_gotoxy(0,0);
lcd_puts("DC Voltage :");
lcd_gotoxy(0,1);
lcd_number(dienthe,2,0);
lcd_gotoxy(4,1);
lcd_putc('V');

}
}
 
H

huunho

Guest
Nói cách khác sửa mỗi lệnh sau:
dienthe= (((ADC10MEM*5)/1023)*100);


thành lệnh sau:

dienthe= (((ADC10MEM*49)/100));

là ok
 

lee_trieu

Gà con
Nói cách khác sửa mỗi lệnh sau:
dienthe= (((ADC10MEM*5)/1023)*100);


thành lệnh sau:

dienthe= (((ADC10MEM*49)/100));

là ok
OK Nó chạy như ý em muốn rồi !!Nhưng anh có thể giải thích giúp em sao phải đổi như ở trên không ạ??
sao mình có số 49 được ạ??? :-( trong khi ta có công thức tổng quát cho ADC 10bit là: Vin = (ADC10MEM * Vref *100)/1023
:5cool_sweat:Cảm ơn anh nhiều lắm !!
 
H

huunho

Guest
bạn thật sự không hiểu a? thế này nhé:
dienthe= (((ADC10MEM*5)/1023)*100) = adc10mem*500/1023
500/1023 = 0.48875 = 0.49
adc10mem*500/1023 = adc10mem*49/100
viết thế này gây lỗi trong quá trình tính toán : dienthe= (((ADC10MEM*5)/1023)*100)
mặc dù không sai về logic, cụ thể là sau phép chia thì sẽ cho số thập phân nhỏ nên bị bỏ qua các số bé sau dấu phẩy.
thế đấy
 

lee_trieu

Gà con
bạn thật sự không hiểu a? thế này nhé:
dienthe= (((ADC10MEM*5)/1023)*100) = adc10mem*500/1023
500/1023 = 0.48875 = 0.49
adc10mem*500/1023 = adc10mem*49/100
viết thế này gây lỗi trong quá trình tính toán : dienthe= (((ADC10MEM*5)/1023)*100)
mặc dù không sai về logic, cụ thể là sau phép chia thì sẽ cho số thập phân nhỏ nên bị bỏ qua các số bé sau dấu phẩy.
thế đấy
Ah em hiểu rồi !!!=))Qua giờ em cứ ngi ngi là cái biến dienthe nó làm tròn nên không có phần thập phân. Rồi em làm được lấy 3 hoặc 4 số sau dấu phẩy luôn rồi, cảm ơn anh nhiều lắm !! :)

Sẵn tiện anh cho em hỏi luôn là em muốn đọc nhiều kênh ADC cùng lúc thì phải config như thế nào luôn ạ ! Em có xem sample code đọc 3 kênh ADC nhưng em không biết giá trị đọc về được lưu ở đâu và lấy nó ra bằng cách nào ạ >?????:-s
 
H

huunho

Guest
đọc xong thì dữ liệu lưu ở adc10mem,bạn phải lưu lại giá trị ở thanh ghi này vào 1 biến toàn cục trước khi đọc tiếp ở 1 chân khác.
thế đấy
 
H

huunho

Guest
bạn cho hỏi thư viện hàm con trên IAR khai báo thế nào? mình muốn dùng hàm _delay_cycles(15);
 

lee_trieu

Gà con
đọc xong thì dữ liệu lưu ở adc10mem,bạn phải lưu lại giá trị ở thanh ghi này vào 1 biến toàn cục trước khi đọc tiếp ở 1 chân khác.
thế đấy
Anh nói rõ hơn giúp em nha! Em chưa hiểu lắm:-(
Em nói vậy anh xem có đúng không nha:
- Đầu tiên Enable ADC.
- Đọc giá trị tại ADC10MEM rồi tắt ADC
- Lưu giá trị vào mảng
- Enable ADC lại
- Đọc giá trị tại ADC10MEM rồi tắt ADC
- Lưu giá trị vào mảng
- ....
:5cool_sweat:Ý tượng vậy không biết đúng ý anh chưa ạ???:-sEm vẫn chưa hiểu làm sao biết được giá trị nào của kênh ADC nào ấy ??:gach
(Hình như ADC lấy mẫu từ kênh cao sau đó giảm dần về kênh A0 hả anh??:5cool_sweat:)
Em cảm ơn anh nhiều !!!:)
 

lee_trieu

Gà con
bạn cho hỏi thư viện hàm con trên IAR khai báo thế nào? mình muốn dùng hàm _delay_cycles(15);
Dạ..trong IAR là có sẵn hàm __delay_cycles(x); đó anh :-(
Nếu mình cấu hình xung 1MHz thì hàm sau có chức năng delay 1s:-s
__delay_cycles(1000000);
 
H

huunho

Guest
trước khi enable adc lại phài config kênh adc tiếp theo, rồi mới làm như bạn nói, chọn kênh adc thế nào thì xem lại ví dụ mẫu nhé.
mình phải include< > cái gì để dùng hàm __delay_cycles(x)__delay_cycles(x)
 

Carue

Trứng gà
đọc xong thì dữ liệu lưu ở adc10mem,bạn phải lưu lại giá trị ở thanh ghi này vào 1 biến toàn cục trước khi đọc tiếp ở 1 chân khác.
thế đấy
Anh nói rõ hơn giúp em nha! Em chưa hiểu lắm:-(
Em nói vậy anh xem có đúng không nha:
- Đầu tiên Enable ADC.
- Đọc giá trị tại ADC10MEM rồi tắt ADC
- Lưu giá trị vào mảng
- Enable ADC lại
- Đọc giá trị tại ADC10MEM rồi tắt ADC
- Lưu giá trị vào mảng
- ....
:5cool_sweat:Ý tượng vậy không biết đúng ý anh chưa ạ???:-sEm vẫn chưa hiểu làm sao biết được giá trị nào của kênh ADC nào ấy ??:gach
(Hình như ADC lấy mẫu từ kênh cao sau đó giảm dần về kênh A0 hả anh??:5cool_sweat:)
Em cảm ơn anh nhiều !!!:)
Không nhất thiết phải theo thứ tự đâu bạn, mình trích ra một đoạn code mình nghĩ có thể giúp được bạn. Cụ thể là mình lấy 3 tín hiệu ở 3 kênh khác nhau trong đó có: kênh 10 temp nội trong g2553, kênh 6 mình lấy thông tin điện thế, kênh 7 đọc nhiệt độ từ lm35. bạn có thể chọn độc lập nguồn điện têế tham chiếu cho nó luôn ah, thí dụ như với kênh A6-7 mình chon là ngôồn nội 1.5 V còn temp nội bên trong chip mình chọn là AVCC. Bạn chịu khó xem như thế tạm đi tại cái này là một phần nhỏ trong bộ thu thập dữ liêu RF của mình

Code:
void Read_Volt_Temp()
{
    volatile long value;
    int results[3];
    unsigned char degC;
    // Temp Sensor ben trong uC
    ADC10CTL1 = INCH_10 + ADC10DIV_3;      // Temp Sensor ADC10CLK/4
    ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );    // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;            // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled
    results[0] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
 
  // Volt-meter
    ADC10CTL1 = INCH_6;                      // ADC ->> volt-meter
    ADC10CTL0 =SREF_1|ADC10SHT_2|REFON|ADC10ON|ADC10IE|ADC10SR|REFBURST;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[1] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
  // Temp Sensor ben ngoai uC (lm35)    kenh A7
   
    ADC10CTL1 = INCH_7;                      // ADC ->> volt-meter
    ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[2] = ADC10MEM;
    ADC10CTL0 &= ~ENC; 
   
    ADC10CTL0 &= ~(REFON + ADC10ON);          // turn off A/D to save power
//============================================================================
//============================================================================
    // Xu ly ket qua Temp Sensor ben trong uC
    value = results[0];
    degC_uC = ((value - 673) * 423) / 1024;
   
   
    // Xu ly ket qua dien ap
    value = results[1];
    //volt = (value*25)/512;
    // Hien thi du lieu dien ap
    volt= (int)((value*quantum)*1000);
    //__no_operation();
    // Xu ly ket qua lm35
    value = results[2];
    degC_lm35 = (float)(value/6.8);
 
}
 
H

huunho

Guest
adc chỉ lấy mẫu 1 kênh được chỉ định thôi, không lấy mẫu lần lượt đâu
 

lee_trieu

Gà con
Không nhất thiết phải theo thứ tự đâu bạn, mình trích ra một đoạn code mình nghĩ có thể giúp được bạn. Cụ thể là mình lấy 3 tín hiệu ở 3 kênh khác nhau trong đó có: kênh 10 temp nội trong g2553, kênh 6 mình lấy thông tin điện thế, kênh 7 đọc nhiệt độ từ lm35. bạn có thể chọn độc lập nguồn điện têế tham chiếu cho nó luôn ah, thí dụ như với kênh A6-7 mình chon là ngôồn nội 1.5 V còn temp nội bên trong chip mình chọn là AVCC. Bạn chịu khó xem như thế tạm đi tại cái này là một phần nhỏ trong bộ thu thập dữ liêu RF của mình

Code:
void Read_Volt_Temp()
{
    volatile long value;
    int results[3];
    unsigned char degC;
    // Temp Sensor ben trong uC
    ADC10CTL1 = INCH_10 + ADC10DIV_3;      // Temp Sensor ADC10CLK/4
    ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );    // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;            // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled
    results[0] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
 
  // Volt-meter
    ADC10CTL1 = INCH_6;                      // ADC ->> volt-meter
    ADC10CTL0 =SREF_1|ADC10SHT_2|REFON|ADC10ON|ADC10IE|ADC10SR|REFBURST;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[1] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
  // Temp Sensor ben ngoai uC (lm35)    kenh A7
 
    ADC10CTL1 = INCH_7;                      // ADC ->> volt-meter
    ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[2] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
 
    ADC10CTL0 &= ~(REFON + ADC10ON);          // turn off A/D to save power
//============================================================================
//============================================================================
    // Xu ly ket qua Temp Sensor ben trong uC
    value = results[0];
    degC_uC = ((value - 673) * 423) / 1024;
 
 
    // Xu ly ket qua dien ap
    value = results[1];
    //volt = (value*25)/512;
    // Hien thi du lieu dien ap
    volt= (int)((value*quantum)*1000);
    //__no_operation();
    // Xu ly ket qua lm35
    value = results[2];
    degC_lm35 = (float)(value/6.8);
 
}
ủa mấy cái biến này em để kiểu này đúng không anh? Sao build nó báo lỗi quá trời:5cool_sweat:
unsigned int degC_uC,volt,quantum,degC_lm35;
 

Carue

Trứng gà
Không nhất thiết phải theo thứ tự đâu bạn, mình trích ra một đoạn code mình nghĩ có thể giúp được bạn. Cụ thể là mình lấy 3 tín hiệu ở 3 kênh khác nhau trong đó có: kênh 10 temp nội trong g2553, kênh 6 mình lấy thông tin điện thế, kênh 7 đọc nhiệt độ từ lm35. bạn có thể chọn độc lập nguồn điện têế tham chiếu cho nó luôn ah, thí dụ như với kênh A6-7 mình chon là ngôồn nội 1.5 V còn temp nội bên trong chip mình chọn là AVCC. Bạn chịu khó xem như thế tạm đi tại cái này là một phần nhỏ trong bộ thu thập dữ liêu RF của mình

Code:
void Read_Volt_Temp()
{
    volatile long value;
    int results[3];
    unsigned char degC;
    // Temp Sensor ben trong uC
    ADC10CTL1 = INCH_10 + ADC10DIV_3;      // Temp Sensor ADC10CLK/4
    ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );    // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;            // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled
    results[0] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
 
  // Volt-meter
    ADC10CTL1 = INCH_6;                      // ADC ->> volt-meter
    ADC10CTL0 =SREF_1|ADC10SHT_2|REFON|ADC10ON|ADC10IE|ADC10SR|REFBURST;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[1] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
  // Temp Sensor ben ngoai uC (lm35)    kenh A7
 
    ADC10CTL1 = INCH_7;                      // ADC ->> volt-meter
    ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[2] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
 
    ADC10CTL0 &= ~(REFON + ADC10ON);          // turn off A/D to save power
//============================================================================
//============================================================================
    // Xu ly ket qua Temp Sensor ben trong uC
    value = results[0];
    degC_uC = ((value - 673) * 423) / 1024;
 
 
    // Xu ly ket qua dien ap
    value = results[1];
    //volt = (value*25)/512;
    // Hien thi du lieu dien ap
    volt= (int)((value*quantum)*1000);
    //__no_operation();
    // Xu ly ket qua lm35
    value = results[2];
    degC_lm35 = (float)(value/6.8);
 
}
ủa mấy cái biến này em để kiểu này đúng không anh? Sao build nó báo lỗi quá trời:5cool_sweat:
unsigned int degC_uC,volt,quantum,degC_lm35;
bạn khai báo biến toàn cục bên ngoài hàm main ấy:1cool_byebye:
Code:
  int degC_uC, volt;
  float degC_lm35;
  float quantum = 0.004692082111;        // buoc luong tu tren phan cung RF
Tôi thấy mô phỏng trên PROTEUS dở ẹt ah, bạn thử làm mạch thực tế thì hay hơn chú ý là phải thêm 1 tụ hóa 1 đến vài uF (tụ hóa nhé) để lọc nhiểu ngỏ vào là ok, kết quả ADC khá chính xác

 

lee_trieu

Gà con
Tôi thấy mô phỏng trên PROTEUS dở ẹt ah, bạn thử làm mạch thực tế thì hay hơn chú ý là phải thêm 1 tụ hóa 1 đến vài uF (tụ hóa nhé) để lọc nhiểu ngỏ vào là ok, kết quả ADC khá chính xác
Ủa anh !! Hình như trên Msp430g2553 có luôn con sensor nhiệt độ hả anh?? Em nghe nói mà chưa có làm, thấy code ở trên có viết phần đọc nhiệt độ nội này !!=))Nó chính xác không ạ???:-(
 

lee_trieu

Gà con
bạn khai báo biến toàn cục bên ngoài hàm main ấy:1cool_byebye:
PHP:
#include <msp430g2553.h>
#include "conf_lcd.c"
int dienthe;
    int results[3];
    
    unsigned char degC;
unsigned int degC_uC,volt,quantum,degC_lm35;
// chuyen so de hien thi
//Ham nay nhan vao tham so
void Read_Volt_Temp()
{
    volatile long value;
 
    
 
  // Volt-meter
    ADC10CTL1 = INCH_6;                      // ADC ->> volt-meter
    ADC10CTL0 =SREF_1|ADC10SHT_2|REFON|ADC10ON|ADC10IE|ADC10SR|REFBURST;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[1] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
  // Temp Sensor ben ngoai uC (lm35)    kenh A7
   
    ADC10CTL1 = INCH_7;                      // ADC ->> volt-meter
    ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[2] = ADC10MEM;
    ADC10CTL0 &= ~ENC; 
   
    ADC10CTL0 &= ~(REFON + ADC10ON);          // turn off A/D to save power
//============================================================================
//============================================================================
    // Xu ly ket qua Temp Sensor ben trong uC
    value = results[0];
    degC_uC = ((value - 673) * 423) / 1024;
   
   
    // Xu ly ket qua dien ap
    value = results[1];
    //volt = (value*25)/512;
    // Hien thi du lieu dien ap
    volt= (int)((value*quantum)*1000);
    //__no_operation();
    // Xu ly ket qua lm35
   value = results[2];
   degC_lm35 = (float)(value/6.8);
 
}
void adc_lcd(int i)
{
    char a, b, c, d;       //tach hang ngan, tram, chuc, don vi
    a = i/1000;
    b = (i - 1000*a)/100;
    c = (i - 1000*a - 100*b)/10;
    d = i - 1000*a - 100*b - 10*c;
    //HIEN THI LEN LCD
    lcd_putc(a + 0x30);
    lcd_puts(".");
    lcd_putc(b + 0x30);
    lcd_putc(c + 0x30);
    lcd_putc(d + 0x30);
    lcd_puts(" V");
}
int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled
  ADC10CTL1 = INCH_1 + CONSEQ_2;                      // input A1
  ADC10AE0 |= 0xff;                         // PA.1 ADC option select
  P2DIR |= 0xff;   
  //ADC10DTC1 = 0x03;                         // 3 conversions
  __bis_SR_register(GIE);  
  conf_lcd(0);
  lcd_clear();
  for (;;)
  {
   ADC10CTL0 &= ~ENC;
   while (ADC10CTL1 & BUSY);   // Wait ADC read0
   /*
   dienthe= (((ADC10MEM*5)/1023)*100) = adc10mem*500/1023
   ma 500/1023 = 0.48875 ~ 0.49 (49/100)
   suy ra: => adc10mem*500/1023 = adc10mem*49/100
   http://www.payitforward.edu.vn/forum/threads/1444/#post-10999
   */
   Read_Volt_Temp();
   dienthe= (((results[2]*49/10)));
   
   ADC10CTL0 |= ENC + ADC10SC;  // Sampling and conversion start
  
    
    lcd_gotoxy(0,0);
    lcd_puts("Dien ap: Kenh 1");
    lcd_gotoxy(0,1);  
    lcd_number(dienthe,3,0);
    lcd_gotoxy(5,1);  
    lcd_putc('V');
 
  }
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
  
  P2OUT ^= BIT6;
  __delay_cycles(100000);
 
}
Em thử đem code ở trên buid thử nhưng nó lại báo lỗi thế này:-s
Code:
Building configuration: new code - Debug 
Updating build tree... 
main.c  
Warning[Pa093]: implicit conversion from floating point to integer C:\Users\LeThanh\Desktop\ADC\New code\main.c 50 
Linking 
Error[e104]: Failed to fit all segments into specified ranges. Problem discovered  
in segment CODE. Unable to place 29 block(s) (0xa22 byte(s) total) in 0x7a4  
byte(s) of memory. The problem occurred while processing the segment  
placement command "-P(CODE)CODE=F800-FFDF", where at the moment of  
placement the available memory ranges were "CODE:f83c-ffdf" 
Error while running Linker 
 
Total number of errors: 1 
Total number of warnings: 1
Hình như là nó tràn bộ nhớ chứa code hay ấy:-(
 

Carue

Trứng gà
:)
bạn khai báo biến toàn cục bên ngoài hàm main ấy:1cool_byebye:
PHP:
#include <msp430g2553.h>
#include "conf_lcd.c"
int dienthe;
    int results[3];
   
    unsigned char degC;
unsigned int degC_uC,volt,quantum,degC_lm35;
// chuyen so de hien thi
//Ham nay nhan vao tham so
void Read_Volt_Temp()
{
    volatile long value;
 
   
 
  // Volt-meter
    ADC10CTL1 = INCH_6;                      // ADC ->> volt-meter
    ADC10CTL0 =SREF_1|ADC10SHT_2|REFON|ADC10ON|ADC10IE|ADC10SR|REFBURST;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[1] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
  // Temp Sensor ben ngoai uC (lm35)    kenh A7
 
    ADC10CTL1 = INCH_7;                      // ADC ->> volt-meter
    ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
    for( degC = 240; degC > 0; degC-- );      // delay to allow reference to settle
    ADC10CTL0 |= ENC + ADC10SC;              // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);          // LPM0 with interrupts enabled
    results[2] = ADC10MEM;
    ADC10CTL0 &= ~ENC;
 
    ADC10CTL0 &= ~(REFON + ADC10ON);          // turn off A/D to save power
//============================================================================
//============================================================================
    // Xu ly ket qua Temp Sensor ben trong uC
    value = results[0];
    degC_uC = ((value - 673) * 423) / 1024;
 
 
    // Xu ly ket qua dien ap
    value = results[1];
    //volt = (value*25)/512;
    // Hien thi du lieu dien ap
    volt= (int)((value*quantum)*1000);
    //__no_operation();
    // Xu ly ket qua lm35
  value = results[2];
  degC_lm35 = (float)(value/6.8);
 
}
void adc_lcd(int i)
{
    char a, b, c, d;      //tach hang ngan, tram, chuc, don vi
    a = i/1000;
    b = (i - 1000*a)/100;
    c = (i - 1000*a - 100*b)/10;
    d = i - 1000*a - 100*b - 10*c;
    //HIEN THI LEN LCD
    lcd_putc(a + 0x30);
    lcd_puts(".");
    lcd_putc(b + 0x30);
    lcd_putc(c + 0x30);
    lcd_putc(d + 0x30);
    lcd_puts(" V");
}
int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                // Stop WDT
  ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled
  ADC10CTL1 = INCH_1 + CONSEQ_2;                      // input A1
  ADC10AE0 |= 0xff;                        // PA.1 ADC option select
  P2DIR |= 0xff; 
  //ADC10DTC1 = 0x03;                        // 3 conversions
  __bis_SR_register(GIE); 
  conf_lcd(0);
  lcd_clear();
  for (;;)
  {
  ADC10CTL0 &= ~ENC;
  while (ADC10CTL1 & BUSY);  // Wait ADC read0
  /*
  dienthe= (((ADC10MEM*5)/1023)*100) = adc10mem*500/1023
  ma 500/1023 = 0.48875 ~ 0.49 (49/100)
  suy ra: => adc10mem*500/1023 = adc10mem*49/100
  http://www.payitforward.edu.vn/forum/threads/1444/#post-10999
  */
  Read_Volt_Temp();
  dienthe= (((results[2]*49/10)));
 
  ADC10CTL0 |= ENC + ADC10SC;  // Sampling and conversion start
 
   
    lcd_gotoxy(0,0);
    lcd_puts("Dien ap: Kenh 1");
    lcd_gotoxy(0,1); 
    lcd_number(dienthe,3,0);
    lcd_gotoxy(5,1); 
    lcd_putc('V');
 
  }
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
 
  P2OUT ^= BIT6;
  __delay_cycles(100000);
 
}
Em thử đem code ở trên buid thử nhưng nó lại báo lỗi thế này:-s
Code:
Building configuration: new code - Debug
Updating build tree...
main.c 
Warning[Pa093]: implicit conversion from floating point to integer C:\Users\LeThanh\Desktop\ADC\New code\main.c 50
Linking
Error[e104]: Failed to fit all segments into specified ranges. Problem discovered 
in segment CODE. Unable to place 29 block(s) (0xa22 byte(s) total) in 0x7a4 
byte(s) of memory. The problem occurred while processing the segment 
placement command "-P(CODE)CODE=F800-FFDF", where at the moment of 
placement the available memory ranges were "CODE:f83c-ffdf"
Error while running Linker
 
Total number of errors: 1
Total number of warnings: 1
Hình như là nó tràn bộ nhớ chứa code hay ấy:-(
Chắc bạn dung CCS quá, mình thì IAR thôi:D


Tùy vào con chip bạn sử dụng riêng g2553 thì khó hết với level code của mình đâu, chắc bạn mô phỏng mấy con bé tí trên proteus chứ gì? Temp nội là tương đối thôi ah tham khảo được
 
Top