PDA

View Full Version : Em có vài câu hỏi nhỏ về PIC với DS1307


HTAluvBeBeo
09-03-2008, 08:10 PM
Chào các bác ạ
Trước tiên rất cám ơn các bác đã vào đọc.
Em có một số câu hỏi rất gà, về một vấn đề cũng cũ lắm rồi,
PIC với DS1307. (em dùng CCS C làm trình dịch)
Có lẽ em không phải dân kĩ thuật và kiến thức lập trình chưa vững nữa nên có tham khảo rồi, vẫn có một số điều chưa hiểu:

Thứ nhất, ds1307 xuất nhập giá trị dạng BCD, ví dụ nó truyền đến pic giá trị giây sec=15 giây chẳng hạn, thì pic sẽ nhận đuơc giá trị nào: 0001 0101 hay là 0x15 (viết có vẻ giống dạng hex 0x nhưng vẫn là BCD các bác nhỉ)?

Thứ 2, em sử dụng code library có sẵn cho ds1307, trong đó đã có hàm bin2bcd và bcd2bin, nghĩa là giá trị ra vào pic từ rtc sẽ là dạng bin. Em gán giá trị đó vào biến sec, biến sec này đuợc khai báo ở đầu là dạng int. Vậy, giả sử biến sec đuợc gán giá trị lấy từ rtc là sec=0b00001111 tuơng ứng với 15 giấy như trên và em có lệnh abc = sec/10 thì abc sẽ là 7 hay là 1 ? Nghĩa là trình dịch có tự convert giá trị dạng bin sang int khi nhận giá trị dạng bin từ rtc nhét vào biến sec không ạ, hay phải làm thế nào ạ.

Cảm ơn các bác đã quan tâm.
Em rất mong đuợc học hỏi

namqn
09-03-2008, 08:30 PM
Chào các bác ạ
Trước tiên rất cám ơn các bác đã vào đọc.
Em có một số câu hỏi rất gà, về một vấn đề cũng cũ lắm rồi,
PIC với DS1307. (em dùng CCS C làm trình dịch)
Có lẽ em không phải dân kĩ thuật và kiến thức lập trình chưa vững nữa nên có tham khảo rồi, vẫn có một số điều chưa hiểu:

Thứ nhất, ds1307 xuất nhập giá trị dạng BCD, ví dụ nó truyền đến pic giá trị giây sec=15 giây chẳng hạn, thì pic sẽ nhận đuơc giá trị nào: 0001 0101 hay là 0x15 (viết có vẻ giống dạng hex 0x nhưng vẫn là BCD các bác nhỉ)?

Thứ 2, em sử dụng code library có sẵn cho ds1307, trong đó đã có hàm bin2bcd và bcd2bin, nghĩa là giá trị ra vào pic từ rtc sẽ là dạng bin. Em gán giá trị đó vào biến sec, biến sec này đuợc khai báo ở đầu là dạng int. Vậy, giả sử biến sec đuợc gán giá trị lấy từ rtc là sec=0b00001111 tuơng ứng với 15 giấy như trên và em có lệnh abc = sec/10 thì abc sẽ là 7 hay là 1 ? Nghĩa là trình dịch có tự convert giá trị dạng bin sang int khi nhận giá trị dạng bin từ rtc nhét vào biến sec không ạ, hay phải làm thế nào ạ.

Cảm ơn các bác đã quan tâm.
Em rất mong đuợc học hỏi
0001 0101 = 0x15 (chỉ là 2 cách viết khác nhau). BCD sử dụng 4 bit nhị phân để biểu diễn một chữ số thập phân.

Các hàm bin2bcd và bcd2bin cho phép bạn chuyển đổi giữa kiểu dữ liệu BCD của RTC và nhị phân của vi điều khiển. int tất nhiên là một trong những kiểu dữ liệu nhị phân. Với ví dụ của bạn, sec = 0b00001111 (15 giây), khi đó adc = sec/10 = 1 (phần nguyên khi chia 15 cho 10). Bạn cần xem lại prototype của các hàm bin2bcd và bcd2bin để biết chúng chấp nhận biến nhị phân kiểu gì, và chuyển kiểu khi tính toán trong trường hợp cần thiết.

Thân,

HTAluvBeBeo
09-03-2008, 09:22 PM
Vâng ạ, như vậy viết theo hai cách đều đuợc

prototype của 2 hàm chuyển đổi định dạng BYTE
BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);
như vậy em khai báo biến sec là int và biến sec này nhận giá trị return từ 2 hàm trên thì vẫn tính toán bình thường anh nhỉ

Rất cảm ơn anh Nam, vì câu hỏi cơ bản thế này cũng đuợc anh chỉ bảo tận tình. Em không đuợc học cơ bản nên chỉ biết đọc và hỏi thôi ạ.

HTAluvBeBeo
14-03-2008, 09:51 AM
cho em hỏi thêm một câu là em dùng CCS C thì
lệnh goto ở trong hàm con có cho phép nhảy qua label nằm ở hàm chính hay hàm con khác không
Ví dụ:
void main(){
//123456
label:
hamcon1();
hamcon2();
}
void hamcon2(){
//abcdef
goto label;
}

như thế có được không ạ

namqn
14-03-2008, 04:27 PM
cho em hỏi thêm một câu là em dùng CCS C thì
lệnh goto ở trong hàm con có cho phép nhảy qua label nằm ở hàm chính hay hàm con khác không
Ví dụ:
void main(){
//123456
label:
hamcon1();
hamcon2();
}
void hamcon2(){
//abcdef
goto label;
}

như thế có được không ạ
Bạn không nên viết như vậy, vì sẽ đảo lộn stack, và rất dễ gây tràn stack. Bạn nên vẽ lưu đồ của thuật toán, và viết chương trình dựa vào đó. Tôi đảm bảo các cấu trúc điều khiển của C sẽ cho phép bạn thực hiện ý đồ thuật toán, mà không phải viết code không chuẩn như vậy.

Thân,

HTAluvBeBeo
14-03-2008, 05:42 PM
Em rất cảm ơn anh Nam và những người quan tâm.
Thú thật là tư duy lập trình của em kém quá. Ngồi cả ngày code đuợc một đoạn ngắn ngắn xong ra toàn error, chữa hết error, (vẫn còn warning), nạp thử nhưng ko chạy. Bản thân em cũng thấy những gì viết ra rất lủng củng và sai nhiều. Em cứ post lên đây các bác quan tâm thì chỉ cho em mấy lỗi cơ bản để em rút kinh nghiệm.

Phần cứng thì cũng không có gì mấy ạ. Em miêu tả tạm thế này ạ
6led A chung. Các chân data là của portB, còn PortA để điều khiển qua 6 trans c1815, giao tiếp với ds1307 là rc3 và rc4.
Riêng phím bấm thì em tham khảo của bác BA giới thiệu
http://dientuvietnam.net/forums/attachment.php?attachmentid=2506&d=1175250495
keyboarout em nhét vào chân RC0. key=1 là mode, 2 là up, 3 là down, 4 là set

Còn một vấn đề có lẽ của bài trước nữa nhưng em hỏi rồi mà vẫn chưa thấu lắm, về bộ đếm ấy ạ. BÁc thử nhìn cái code giao tiếp với ds1307 nó cho ra vào dữ liệu dang binary, còn em lại khai báo những biến đấy trong ct dạng int8. Như vậy có đuợc không ạ,


Quả thật kiến thức của em về PIC cũng như điện tử chưa đâu vào đâu cả nên
Em rất mong đuợc giúp đỡ, nếu đuợc anh Nam giúp đỡ nũa thì mừng quá
có gì sai ngu quá các anh bỏ quá cho, em rất thích điện tử nhưng lại theo chuyên ngành khác, nên kiến thức không đuọc bài bản.

namqn
14-03-2008, 08:35 PM
Bạn xem lại chương trình mà bạn đã tham khảo, ở phần đọc dữ liệu từ DS1307, trong một loạt lệnh i2c_read(), chỉ có lệnh cuối là dùng i2c_read(0), còn những lệnh trước đó là i2c_read(), tức là tương đương với i2c_read(1). Đoạn code trong hàm ds1307_init() của bạn có 2 lệnh gọi i2c_read(0) ở phần đầu, đây chính là chỗ không ổn. Trong một loạt lệnh read từ I2C, mỗi lệnh đều phải ACK trừ lệnh sau cùng, để báo cho slave biết là master không muốn đọc nữa.

Bạn đọc thêm về I2C ở đây:
https://www2.hcmut.edu.vn/~nqnam/Commu.php#i2c

Và tham khảo thêm tập tin nguồn "Vidu4-4.c" trong tutorial 4 dành cho dsPIC của tôi, tôi đã chú thích thứ tự những thao tác cần thực hiện khi giao tiếp với DS1307.

Thân,

HTAluvBeBeo
14-03-2008, 08:38 PM
em không rõ là chỗ interrupts có đúng không nữa
có lẽ em hiểu về interrupts sai
Em hiểu nôm na thế này
PIC nó đang trơn tru làm một gói việc A thì bị interrupts và bắt nó nhảy sang làm việc B, làm xong việc B rồi nó lại quay lại chỗ đang làm dở việc A
Hiểu nôm na thế có sai không ạ

PS:
bây giờ mới đọc đuợc bài của anh
em có hiểu sơ qua về i2c, ví dụ trong truơng hợp write. quá trình gửi mỗi 8bit từ master thì sẽ theo sau một ACK (acknowledge) của slave để thông báo
Em cũng thắc mắc về cái thư viện code nhặt đuợc ở trên, có giở qua CCS manual mà lại đọc không kĩ, vậy là 0 là nack, 1 là ack, em sẽ xem lại thêm ạ, tham khảo thêm phần anh viết ạ. Cũng tại copy paste dòng dưới lên dòng trên mà không kiểm tra lại
thanks anh Nam nhiều
anh nhiệt tình quá

HTAluvBeBeo
15-03-2008, 12:48 PM
em đổi lại phần cứng rồi ạ, kiểu vừa quét led vừa bắt phím em làm chưa tốt
em chuyển phím bấm vào 3 chân RC0 1 2


mọi thứ đã tốt hơn nhiều rồi ạ.
em vẫn chưa làm đuợc kiểu quét phím tiết kiêm chân, phải dùng thêm 3 chân nữa để bắt phím


Thêm một cái nữa là em muốn tăng giảm độ sáng của led 7T thì làm thế nào ạ, bác nào giải thích cho em với ạ

Một lần nữa rất cám ơn anh Nam đã quan tâm.
Vậy là em mới làm xong time và date mode thôi, còn âm lịch, báo thức nữa
Mong sẽ không phải làm phiền anh:D
PS: em tìm ra lỗi rồi ạ, em dùng ngắt ngoài với chan RB0 đồng thời dùng portB đẻ đưa data vào led 7T nên bị thế ạ
Vậy em phải làm thế nào để vừa dùng ngắt ngoài vừa dùng PORTB để đưa data vào leds ạ
Thanks

HTAluvBeBeo
16-03-2008, 01:33 PM
Sáng nay đọc thêm về timer nên đã làm 2 code, một dùng ds1307 và một chỉ dùng timer
dùng timer1 tạo ngắt, rồi đếm system clock (chứ không phải đếm số lần interrupt nên chính xác hơn) cho 1s lại update ds1307 một lần, Có vẻ tốt hơn rồi
Đồng thời làm thêm đồng hồ số dựa trên timer, cho ra giá trị đúng 1s, em đang test rồi. cả hai cái đều chưa phát hiện thêm bug. Sai số phần lớn do XTAL
Dùng timer như vậy có lợi thế nhỏ gọn hơn nhưng không có pin backup nên mất điện thì setup lại.

#define XTAL_FREQUENCY 20000000
#use delay(clock=XTAL_FREQUENCY)
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4) //TIMER1_F =5000000

ticker = TIMER1_FREQUENCY;
#int_TIMER1
void TIMER1_isr()
{
ticker -= 65536; // Decrement ticker by clocks per interrupt
if ( ticker < 65536 ) // If second has expired~76 TIMES
{ ticker += TIMER1_FREQUENCY; // Increment ticker by clocks per second
sec++; // Increment number of seconds
}}
Em vẫn muôns hỏi thêm về cách làm cho led 7T hiển thị tăng giảm độ sáng được ạ
Thanks
PS: lần sau em sẽ rút kinh nghiệm không post code dài nữa ạ để tránh người đọc topic thấy chán ngán

picthanh
24-03-2008, 01:36 PM
chào anh namqn và cá c anh em khác trong topic này . em đang làm con DS1307 bữa giờ , giao tiếp thành công rồi đọc set gia tri cho nó cũng được luôn rồi , chỉ mỗi tội là ko hiểu sao nó chạy hơn đồng hồ bình thường .cụ thể thế này : giả sử giờ hiện tại là 0h em set giá trị hour=0, minute=0, sec=0 và cho nó chạy, nó chạy bình thường, em canh đúng 1 tiếng đồng hồ với cái đồng hồ trên computer và xem lại thì cái đồng hồ chạy bằng con DS1307 chỉ mới chạy được 30 phút, vậy là do lý do gì, em thử so sánh 1 phút của nó cũng chay chậm hơn đồng hồ thường của mình. Em cung thư với cả hai loại VDK PIC và AVR đều cho chung kết quả như nhau. em đã cho thạch anh nằm gần sát với 2 chân dao động của con DS1307 .anh em nào bit tại sao chỉ giúp với.

minhsondaklak
24-03-2008, 04:04 PM
Nhân tiện xin hỏi thêm các huynh về số BCD trong ds1307 như sau:
Nếu ta ghi vào ds1307 giá trị là 0x15 thì nó nhận là 00010101 ở dạng BCD (giá trị = 15 thập phân).
Như vậy, cùng một số 0x15, con ds1307 sẽ nhận là 15, còn con Pic nhận là 21 thập phân ?
Không biết em hiểu như vậy đã chính xác chưa, có gì nhờ các huynh chỉ giáo.

bien_van_khat
24-03-2008, 05:08 PM
Nếu ta ghi vào ds1307 giá trị là 0x15 thì nó nhận là 00010101 ở dạng BCD (giá trị = 15 thập phân).
Như vậy, cùng một số 0x15, con ds1307 sẽ nhận là 15, còn con Pic nhận là 21 thập phân ?


Đúng rồi, vấn đề ở đây là ký hiệu 0x15 được xét trong hệ đếm hay hệ mã hóa nào.

Trong hệ đếm 16, số 21 (hệ đếm 10) được biểu là 15, và thường đc ký hiệu là 0x15 (0x ám chỉ con số sau nó ở hệ cơ số 16)

Nhưng cũng số 21 (hệ đếm 10) nếu xét trong hệ mã hóa BCD thì nó có giá trị là 15 (hệ đếm 10).

namqn
24-03-2008, 06:19 PM
chào anh namqn và cá c anh em khác trong topic này . em đang làm con DS1307 bữa giờ , giao tiếp thành công rồi đọc set gia tri cho nó cũng được luôn rồi , chỉ mỗi tội là ko hiểu sao nó chạy hơn đồng hồ bình thường .cụ thể thế này : giả sử giờ hiện tại là 0h em set giá trị hour=0, minute=0, sec=0 và cho nó chạy, nó chạy bình thường, em canh đúng 1 tiếng đồng hồ với cái đồng hồ trên computer và xem lại thì cái đồng hồ chạy bằng con DS1307 chỉ mới chạy được 30 phút, vậy là do lý do gì, em thử so sánh 1 phút của nó cũng chay chậm hơn đồng hồ thường của mình. Em cung thư với cả hai loại VDK PIC và AVR đều cho chung kết quả như nhau. em đã cho thạch anh nằm gần sát với 2 chân dao động của con DS1307 .anh em nào bit tại sao chỉ giúp với.
Thạch anh 32768 Hz ngoài thị trường là linh kiện không chuẩn nhất trong mạch này. Bạn thử với một vài thạch anh khác xem sao. Rất ít khả năng vi mạch DS1307 hoạt động sai. Thạch anh 32768 Hz thường khó sử dụng hơn các loại thạch anh tần số cỡ MHz, vì mức công suất (drive level) của thạch anh 32768 Hz thấp hơn hàng chục, thậm chí hàng trăm lần so với thạch anh tầm MHz. Do đó, chúng ta rất dễ overdrive các thạch anh 32768 Hz.

Thân,

picthanh
25-03-2008, 01:05 AM
em thử với thạch anh khác rồi , kết quả là nó còn chậm hơn cái thạch anh cũ. bây giờ làm sao đây anh , thay luôn con ds1307 mới luôn hả anh. sáng mai em định mang cả cái mạch đi nhờ cái máy hiện sóng kiểm tra thử xem thạch anh có hoạt động đúng tần số chưa (bằng cách đo xung ơ chân của thạch anh dao động khi mạch đang hoạt động , ko bít có đúng ko).

namqn
25-03-2008, 01:32 AM
em thử với thạch anh khác rồi , kết quả là nó còn chậm hơn cái thạch anh cũ. bây giờ làm sao đây anh , thay luôn con ds1307 mới luôn hả anh. sáng mai em định mang cả cái mạch đi nhờ cái máy hiện sóng kiểm tra thử xem thạch anh có hoạt động đúng tần số chưa (bằng cách đo xung ơ chân của thạch anh dao động khi mạch đang hoạt động , ko bít có đúng ko).
Như vậy có thể thấy những thạch anh mà bạn đã dùng là không tốt. Bạn không nên đo tần số của thạch anh ngay tại các chân X1 hay X2 của DS1307, vì điện dung của probe sẽ làm thay đổi điện dung tải, dẫn đến thay đổi tình trạng làm việc của mạch dao động. Bạn nên lập trình để có xung ở ngõ ra SQW/OUT (4 kHz chẳng hạn), và dùng dao động ký đo ở chân đó.

DS1307 có sẵn tụ tải 12.5 pF ở bên trong, do đó cần phải lựa chọn thạch anh thích hợp, chứ không phải thạch anh 32.768 kHz nào cũng dùng được với DS1307 đâu.

Thân,

HTAluvBeBeo
25-03-2008, 10:19 AM
bạn picthanh thử kiểm tra lại các chân của ds1307 xem:
Có đầy đủ pullup R chưa, SDA, SCL, SQW/out
Pin 3V Li đã đuợc nối vào chưa, nếu không dùng pin thì chân Vbat phải nhét Ground.

Sai số mình làm cũng tuơng đối lớn 2s/day. Xtal không chuẩn đuơng nhiên rồi, em mua có 15oovnd, với cả cắm trên breadboard nên chưa tối ưu đuợc mạch.
Canh giờ với computer nhiều khi cũng không chính xác đâu. Truơc khi canh lại giờ, bạn update internet time
GL!

picthanh
25-03-2008, 01:40 PM
mình tim ra nguyen nhân rồi. bị phần cứng , mình lắp tạm mạch trên broad đục lỗ, sáng nay sau khi nghịch một tí nó chạy rất tốt , ko bị chậm nữa. tới trưa thì nó bị lại do mình bỏ nó vào trong túi sách mang di mang về. thì nó lại bị ===> mạch có vấn đề.

minhsondaklak
27-03-2008, 04:14 PM
Vẫn còn phân vân, nhưng chưa có điều kiện phần cứng để thử, nên xin hỏi nốt các huynh về số BCD với ds1307 như sau:
-Nếu ghi số 0x15 vào một thanh ghi của ds1307 rồi đọc lại giá trị của thanh ghi đó, sẽ cho kết quả là 0001 0101 (số BCD, giá trị = 15) hay là 0010 0001 (số BCD, giá trị = 21) ?

Xin cảm ơn !

bien_van_khat
27-03-2008, 05:08 PM
Vẫn còn phân vân, nhưng chưa có điều kiện phần cứng để thử, nên xin hỏi nốt các huynh về số BCD với ds1307 như sau:
-Nếu ghi số 0x15 vào một thanh ghi của ds1307 rồi đọc lại giá trị của thanh ghi đó, sẽ cho kết quả là 0001 0101 (số BCD, giá trị = 15) hay là 0010 0001 (số BCD, giá trị = 21) ?

Xin cảm ơn !

vẫn là 0001 0101, vì ds1307 xử lý với số BCD nó ko chuyển đổi gì hết.

Nếu bạn ghi vào là 0000 1001 (9h chẳng hạn) khi tới 10 giờ tức là tăng lên 1, giá trị sẽ là
0001 0000