PDA

View Full Version : mất dữ liệu eeprom


tungtot_vl
11-03-2008, 02:42 PM
cho em hỏi. các bác có gặp trường hợp nào mất dữ liệu trong eeprom không.
tôi viết chương trình chạy chữa quang báo, dọc vào và viết ra chạy bình thường. nhưng đôi khi không chạy 3-5 ngày thì 1 phần dữ liệu trong eeprom bị mật. cũng có trường hợp nó đang chạy, tôi lỡ tay chạm vào các chân píc thì nó cũng mất dữ liệu hoặc có 1 số dữ liệu từ địa chỉ này nhảy sang địa chỉ khác. không hiểu vì sao. vậy khi sóc điện có làm mất dữ liệu trong pic không hả các bác. bác nào gặp rồi thì chỉ cho cách khắc phục với.

namqn
11-03-2008, 04:21 PM
cho em hỏi. các bác có gặp trường hợp nào mất dữ liệu trong eeprom không.
tôi viết chương trình chạy chữa quang báo, dọc vào và viết ra chạy bình thường. nhưng đôi khi không chạy 3-5 ngày thì 1 phần dữ liệu trong eeprom bị mật. cũng có trường hợp nó đang chạy, tôi lỡ tay chạm vào các chân píc thì nó cũng mất dữ liệu hoặc có 1 số dữ liệu từ địa chỉ này nhảy sang địa chỉ khác. không hiểu vì sao. vậy khi sóc điện có làm mất dữ liệu trong pic không hả các bác. bác nào gặp rồi thì chỉ cho cách khắc phục với.
Nói chung chung như bạn thì rất khó xác định nguyên nhân vì sao. Thiết kế phần cứng không tốt và viết code kém có thể dẫn đến hiện tượng này.

Sốc điện mà bạn nói là theo kiểu nào: nguồn tăng/giảm đột ngột, xung áp ở chân MCLR, hay một vài chân I/O bị đặt ở mức điện áp ngoài phạm vi các rail nguồn, hay kiểu sốc nào khác mà tôi chưa biết?

Thân,

tungtot_vl
17-03-2008, 04:33 PM
chào anh nam. khi em chạm tay vào chân của pic thì mất dữ liệu, khi đó em cũng không nhớ chân nào nữa. thế các trường hợp tăng hoặc giảm nguồn đột ngột cũng làm mất data trong eeprom phải không anh.
cho em hỏi luông. pic có 256 byte eeprom thế nếu mình dùng hết toàn bộ 256 byte này để chứa data thì có ảnh hưỡng gì đến việc mất data không anh.
các lệnh khai báo trong config có ảnh hưỡng gì đến việc lưu trữ data trong eeprom của pic không.
anh giải thích dùm em nhé. thank you!

namqn
17-03-2008, 07:00 PM
chào anh nam. khi em chạm tay vào chân của pic thì mất dữ liệu, khi đó em cũng không nhớ chân nào nữa. thế các trường hợp tăng hoặc giảm nguồn đột ngột cũng làm mất data trong eeprom phải không anh.
cho em hỏi luông. pic có 256 byte eeprom thế nếu mình dùng hết toàn bộ 256 byte này để chứa data thì có ảnh hưỡng gì đến việc mất data không anh.
các lệnh khai báo trong config có ảnh hưỡng gì đến việc lưu trữ data trong eeprom của pic không.
anh giải thích dùm em nhé. thank you!
Bạn nên cho biết phần cứng của bạn thiết kế ra sao, code của bạn viết như thế nào (không cần code chi tiết, chỉ cần chương trình chính, và các phần code liên quan đến đọc/ghi EEPROM).

Những câu hỏi trên của bạn liên quan đến nhiều vấn đề, không thể giải thích đơn giản bằng vài đoạn văn bản.

Thân,

tungtot_vl
19-03-2008, 04:47 PM
Bạn nên cho biết phần cứng của bạn thiết kế ra sao, code của bạn viết như thế nào (không cần code chi tiết, chỉ cần chương trình chính, và các phần code liên quan đến đọc/ghi EEPROM).

Những câu hỏi trên của bạn liên quan đến nhiều vấn đề, không thể giải thích đơn giản bằng vài đoạn văn bản.

Thân,

cái này chỉ là từng đoạn chường trình thôi. anh coi có giúp gì được cho em không.

#include<18f4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CP UDIV1,VREGEN,NOBROWNOUT
#device 18F4550*=16 ADC=10
#use delay(clock=48000000)
#include<E:\595\font9moi.c>
#include<E:\595\font7.c>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#priority rda
#use fast_io(a)
#byte porta=0x05
#use fast_io(b)
#byte portb=0x06
#use fast_io(c)
#byte portc=0x07
#use fast_io(d)

#byte portd=0x08
#use fast_io(e)
#byte porte=0x09
#define clk pin_b4
#define data pin_b5
#define lock pin_b6
//********** DIA CHI CAC EPPROM ************************************************
#define add1 0x06 // 30 byte
#define add2 0x25 // 34 byte
#define add3 0x49 // 80 byte
#define add4 0x9f // 100 byte
#define b1 0x01
#define b2 0x02
#define b3 0x03
#define b4 0x04
//==================
void giao_tiep();
void viet_eeprom();
void doc_eeprom1();
void doc_eeprom2();
void doc_eeprom3();
void doc_eeprom4();
void trabang();
#INT_RDA
void giao_tiep()
{ int8 c;
disable_interrupts(global);
output_low(pin_b0); output_low(pin_b1); output_low(pin_b2); output_low(pin_b3);
c = getc();
putc(c);
k=c;
if(k==255)
{
viet_eeprom();
}
else { chu[s]=k; s++; delay_ms(500);}
enable_interrupts(global);
}
//************************************************** **
#INT_EEPROM
void viet_eeprom()
{ int i,l,x;
disable_interrupts(global);
if(chu[0]==251)// chuoi 1
{
write_eeprom(b1,s);
for(i=0;i<s;i++) // s
{ write_eeprom(add1+i,chu[i]); }
}
if(chu[0]==252) // chuoi 2
{
write_eeprom(b2,s);
for(i=0;i<s;i++) // s
{ write_eeprom(add2+i,chu[i]); }
}
if(chu[0]==253)// chuoi 3
{
write_eeprom(b3,s);
for(i=0;i<s;i++) // s
{ write_eeprom(add3+i,chu[i]); }
}
if(chu[0]==254) // chuoi 4
{
write_eeprom(b4,s);
for(i=0;i<s;i++) // s
{ write_eeprom(add4+i,chu[i]); }
}

for(i=0;i<s+2;i++) {chu[i] = 10;}
s=0;
printf("W ");
enable_interrupts(global);
}
//************************************************** **
void doc_eeprom1()
{ int i,l;
disable_interrupts(global);
for(i=0;i<f1;i++)
{
l = read_eeprom(add1+i);
chu[i] = l;
}
enable_interrupts(global);
printf("C1 ");
}
//************************************************** ********
void doc_eeprom2()
{ int i,l;
disable_interrupts(global);
for(i=0;i<f2;i++)
{
l = read_eeprom(add2+i);
chu[i] = l;
}
enable_interrupts(global);
printf("C2 ");
}
//************************************************** **
void doc_eeprom3()
{ int i,l;
disable_interrupts(global);
for(i=0;i<f3;i++)
{
l = read_eeprom(add3+i);
chu[i] = l;
}
enable_interrupts(global);
printf("C3 ");
}
//************************************************** ********
void doc_eeprom4()
{ int i,l;
disable_interrupts(global);
for(i=0;i<f4;i++)
{
l = read_eeprom(add4+i);
chu[i] = l;
}
enable_interrupts(global);
printf("C4 ");
}
//====================


void main()
{
set_tris_b(0);
set_tris_a(0);
set_tris_c(0);
set_tris_e(0);
set_tris_d(0);
output_b(0);
output_e(16);
enable_interrupts(INT_eeprom);
enable_interrupts(INT_RDA);
enable_interrupts(global);
printf("v ");
delay_ms(3000);
while(true)
{
// printf("/");
f1 = read_eeprom(b1); f2 = read_eeprom(b2);
f3 = read_eeprom(b3); f4 = read_eeprom(b4);
doc_eeprom1();
trabang();
doc_eeprom2();
trabang();
doc_eeprom3();
trabang();
doc_eeprom4();
trabang();
trabang1();
dichtrai1();

}
}

namqn
19-03-2008, 09:28 PM
Tôi không dùng CCS C, nhưng đọc qua code của bạn, tôi có cảm giác không ổn. Theo tài liệu của CCS C, #INT_EEPROM là ngắt xảy ra khi việc ghi EEPROM hoàn tất. Những gì bạn viết trong trình xử lý ngắt #INT_RDA có thể hiểu được, nhưng những gì bạn viết trong trình xử lý ngắt #INT_EEPROM thì khó hiểu.

Theo cách bạn viết, khi nhận được ký tự, và ký tự đó có giá trị 255 thì bạn sẽ thực hiện việc ghi vào EEPROM. Tuy nhiên, chương trình con mà bạn gọi ở trình xử lý ngắt #INT_RDA lại là trình xử lý ngắt #INT_EEPROM, điều này có thể gây ra rắc rối, vì chương trình xử lý ngắt sẽ trở về bằng lệnh RETI, còn chương trình con bình thường sẽ trở về bằng lệnh RETURN hay RETLW.

Điểm thứ hai, ngắt #INT_EEPROM xảy ra khi việc ghi 1 ô nhớ EEPROM hoàn tất, khi đó, trong chương trình xử lý ngắt #INT_EEPROM của bạn, bạn lại yêu cầu ghi vào EEPROM nữa, vì khi động tác ghi này hoàn tất, nó sẽ sinh ra một ngắt #INT_EEPROM nữa. Trong khi đó, bạn vẫn chưa hoàn tất vòng lặp ghi một mảng giá trị vào EEPROM. Thực sự tôi cũng không hiểu chương trình này sẽ vận hành như thế nào, vì tôi không bao giờ viết code kiểu như vậy.

Thân,

tungtot_vl
22-03-2008, 11:40 AM
bài viết của em là khi có data từ pc gởi xuống thì lưu vào mang chu[]. và khi gặp giá trị 255 tức là giá trị kết thúc chuổi đã gởi và gọi chương trình viết vào eeprom. việc viết vào địa chỉ eeprom tuỳ thuộc vào giá trị chu[0] trong chuổi để chọn các địa chỉ khác nhau (add1 .. add4). do đó khi đọc các chuổi trong eeprom ra thì chọn đại chỉ nào thì đọc được địa chỉ đó và đọc đúng chuổi gởi vào.
cách giải thích của anh em cũng chưa hiểu rỏ lắm và chưa biết cách khác phục lại phần mềm như thế nào mong anh chỉ rỏ thêm

namqn
22-03-2008, 07:11 PM
Cách tốt nhất là bạn tham khảo ví dụ ghi EEPROM của CCS C và chỉnh sửa lại cho phù hợp với yêu cầu của bạn.

Lấy ví dụ đơn giản, bạn có chuỗi 1 sẽ được ghi vào EEPROM. Ở đầu hàm viet_eeprom(), bạn đã cấm ngắt toàn cục. Khi thực hiện ghi chuỗi 1, bạn gọi hàm write_eeprom(b1, s) để ghi lại giá trị của s. Về nguyên tắc, hàm write_eeprom() của CCS C dùng khả năng ghi vào EEPROM của phần cứng bên trong PIC, do đó sẽ kích hoạt cờ EEIF khi đã ghi xong byte s đó vào b1. Theo yêu cầu của phần cứng, có lẽ hàm write_eeprom() của CCS C sẽ xóa cờ EEIF trong trường hợp polling và để nguyên nó nếu bạn có dùng #INT_EEPROM (để trình phục vụ ngắt #INT_EEPROM có thể xử lý như thiết kế).

Vì ngắt toàn cục đã bị cấm, hàm viet_eeprom() của bạn tiếp tục chạy đến vòng lặp để ghi chuỗi vào vùng nhớ add1. Như đã nói ở trên, cứ sau mỗi lần ghi được 1 byte vào EEPROM, cờ EEIF sẽ được bật, và có lẽ sẽ không được xóa vì bạn đã khai báo có dùng #INT_EEPROM. Tôi không rõ hàm write_eeprom() sẽ làm gì trong trường hợp này (đây cũng là một trong những lý do khiến tôi không thích những hàm built-in của CCS C, vì hành vi của chúng không được giải thích rõ ràng).

Hành vi của hàm viet_eeprom() của bạn phụ thuộc vào hành vi không được biết rõ của hàm write_eeprom(). Và cách viết code của bạn là không thân thiện với cấu trúc ngắt của PIC.

Thân,

LeDuc
24-03-2008, 12:30 PM
bài viết của em là khi có data từ pc gởi xuống thì lưu vào mang chu[]. và khi gặp giá trị 255 tức là giá trị kết thúc chuổi đã gởi và gọi chương trình viết vào eeprom. việc viết vào địa chỉ eeprom tuỳ thuộc vào giá trị chu[0] trong chuổi để chọn các địa chỉ khác nhau (add1 .. add4). do đó khi đọc các chuổi trong eeprom ra thì chọn đại chỉ nào thì đọc được địa chỉ đó và đọc đúng chuổi gởi vào.

Theo mình bạn kô nên sử dụng ngắt eeprom , bạn nên viết một hàm con cho việc ghi và đọc eeprom , như vậy sẽ trách được việc ngắt eeprom bi sai vì bạn ghi và đọc cả mãng giá trị lận ..Mình cũng thường sử dụng cách trên để ghi và đọc một mãng giá trị ... Và việc nạp và sử dụng mình chưa bao giờ bị mất dữ liệu trong eeprom ...
Có gì thì trao đổi thêm ha.. !!

tungtot_vl
25-03-2008, 07:50 AM
Lấy ví dụ đơn giản, bạn có chuỗi 1 sẽ được ghi vào EEPROM. Ở đầu hàm viet_eeprom(), bạn đã cấm ngắt toàn cục. Khi thực hiện ghi chuỗi 1, bạn gọi hàm write_eeprom(b1, s) để ghi lại giá trị của s. Về nguyên tắc, hàm write_eeprom() của CCS C dùng khả năng ghi vào EEPROM của phần cứng bên trong PIC, do đó sẽ kích hoạt cờ EEIF khi đã ghi xong byte s đó vào b1. Theo yêu cầu của phần cứng, có lẽ hàm write_eeprom() của CCS C sẽ xóa cờ EEIF trong trường hợp polling và để nguyên nó nếu bạn có dùng #INT_EEPROM (để trình phục vụ ngắt #INT_EEPROM có thể xử lý như thiết kế).

Vì ngắt toàn cục đã bị cấm, hàm viet_eeprom() của bạn tiếp tục chạy đến vòng lặp để ghi chuỗi vào vùng nhớ add1. Như đã nói ở trên, cứ sau mỗi lần ghi được 1 byte vào EEPROM, cờ EEIF sẽ được bật, và có lẽ sẽ không được xóa vì bạn đã khai báo có dùng #INT_EEPROM. Tôi không rõ hàm write_eeprom() sẽ làm gì trong trường hợp này (đây cũng là một trong những lý do khiến tôi không thích những hàm built-in của CCS C, vì hành vi của chúng không được giải thích rõ ràng).

Hành vi của hàm viet_eeprom() của bạn phụ thuộc vào hành vi không được biết rõ của hàm write_eeprom(). Và cách viết code của bạn là không thân thiện với cấu trúc ngắt của PIC.

Thân,[/QUOTE]

vì data từ pc gởi xuống phải được lưu vào eeprom. ví dụ khi gửi xuống chuổi 1 thì chuổi 1 phải được lưu vào mãng chu[] và ghi vào eeprom. và sau đó phải xoá mãng chu[] để tiếp tục lưu chuỗi thứ 2,3...
nếu khi gởi data từ pc xuống mà không lưu vào eeprom ngay thì chuỗi 2 gởi xuống sẽ làm mất chuỗi 1.
còn nếu muốn tách hàm viet_eeprom vào doc_eeprom ra thì cần có nhiều mãng chu[]. mỗi mãng phải lưu 1 chuỗi khác nhau. cách này hơi tốn ram lắm.
em có thể bỏ hàm viet_eeprom xuống cuối hàm giao tiếp PC như phía dưới thì có ổn không.
#INT_RDA

void giao_tiep()
{ int8 c;
disable_interrupts(global);
output_low(pin_b0); output_low(pin_b1); output_low(pin_b2); output_low(pin_b3);
c = getc();
putc(c);
k=c;
if(k==255)
{
//////
}
else { chu[s]=k; s++; delay_ms(500);}
enable_interrupts(global);
viet_eeprom();
}
theo leduc noi không nên dùng ngắt khi viết vào eprom do đó nếu em bỏ các lệnh
#INT_EEPROM
disable_interrupts(global); và enable_interrupts(global);
và vẫn giữ nguyên hàm ngắt giao tiếp pc như cũ thì có ổn không hả các anh.

tungtot_vl
28-03-2008, 05:01 PM
cảm ơn anh nam nhiều anh giải thích cách này thì em đã hiều. để em sửa lại cod xem sao. cảm ơn anh nhiều.

quyenemic
11-04-2008, 11:29 AM
Lỗi này chưa chắc là do chương trình đọc ghi eeprom của bạn đâu, tôi thấy có thể là do bạn chưa đặt BROWNOUT RESET, nên khi nguồn của bạn kém hoặc khi cắm điện chương trình của bạn bị nhảy vào đoạn ghi đọc eeprom và ghi đọc sai...