Ðăng Nhập

View Full Version : Các bác cho em hỏi lỗi về stack trong PIC16F887


pk178
22-11-2009, 10:17 PM
Chào các bác !!!

Hiện em gặp phải vấn đề sau : em dùng PIC16F887, em lập trình bằng CCS, nhưng khi biên dịch nó lại báo lỗi là "Interrupt handler uses too much stack" (lỗi 133).

Em nghĩ có thể do em sử dụng stack nhiều quá nên bị tràn stack, nhưng em không biết khắc phục thế nào cả, em lập trình bằng C nên về phần cứng em gà lắm.

Bác nào có kinh nghiệm với lỗi này xin chỉ giáo cho em với ạ, em xin chân thành cám ơn các bác nhiều ạ !!!

namqn
22-11-2009, 11:02 PM
Chào các bác !!!

Hiện em gặp phải vấn đề sau : em dùng PIC16F887, em lập trình bằng CCS, nhưng khi biên dịch nó lại báo lỗi là "Interrupt handler uses too much stack" (lỗi 133).

Em nghĩ có thể do em sử dụng stack nhiều quá nên bị tràn stack, nhưng em không biết khắc phục thế nào cả, em lập trình bằng C nên về phần cứng em gà lắm.

Bác nào có kinh nghiệm với lỗi này xin chỉ giáo cho em với ạ, em xin chân thành cám ơn các bác nhiều ạ !!!
Nếu cho rằng lỗi là do code thì bạn nên post code của bạn lên. Nên xem qua luồng "Một số đề nghị với các thành viên" có link nằm ở chữ ký của tôi, để đặt câu hỏi tốt hơn.

Thân,

pk178
22-11-2009, 11:27 PM
Cám ơn bác đã cho ý kiến !!!

Thực ra lỗi này em cũng đã hỏi trên diễn đàn rồi, nhưng chưa thấy ai trả lời được, giờ em muốn hỏi lại lần nữa để nhờ mọi người giúp đỡ.

Em đã post bài này ở luồng này

http://www.picvietnam.com/forum//showthread.php?t=5286

Rất mong các bác ra tay giúp đỡ. Em xin chân thành cám ơn các bác nhiều !

namqn
22-11-2009, 11:47 PM
Cám ơn bác đã cho ý kiến !!!

Thực ra lỗi này em cũng đã hỏi trên diễn đàn rồi, nhưng chưa thấy ai trả lời được, giờ em muốn hỏi lại lần nữa để nhờ mọi người giúp đỡ.

Em đã post bài này ở luồng này

http://www.picvietnam.com/forum//showthread.php?t=5286

Rất mong các bác ra tay giúp đỡ. Em xin chân thành cám ơn các bác nhiều !
Trong luồng đó bạn hỏi về chương trình viết cho PIC16F877A, và bạn đã cho biết là chạy được nếu bỏ "keypad_input.c". Do đó, tôi cho rằng vấn đề báo lỗi stack của bạn trong luồng đó đã được giải quyết xong, và luồng này là một vấn đề khác.

Thân,

pk178
22-11-2009, 11:57 PM
Vâng, đúng là trong luồng đó em dùng con 16f877A, nó vẫn bị lỗi đấy, lần này em dùng con 16f887, vẫn bị lỗi đấy (thực ra là 2 con này cũng tương tự nhau thôi ạ).

Em đã thử cái hàm ngắt rồi, em lần lượt thêm vào từng dòng lệnh, mới đầu thì không sao, nhưng khi nhiều dòng lệnh được thêm vào hàm ngắt thì nó báo lỗi này ngay.

Em cũng đã xem 1 số tài liệu hướng dẫn cách lập trình, người ta có nói là chương trình cho ngắt không nên quá dài. Em nghĩ cũng có thể là chương trình ngắt của em dài quá (em có sử dụng kiểu biến int32 trong đó) nên nó bị lỗi này.

Em muốn hỏi các bác xem có cách nào khắc phục lỗi này được không, em có ý tưởng là sau 1 lệnh, mình có thể xóa ngay dữ liệu trong stack đi, rồi tiếp tục thực hiện lệnh tiếp theo, như vậy sẽ ko bị tràn stack nữa.

Cái khó là em không biết thao tác thế nào với ý tưởng này. Bác nào biết thì hướng dẫn em với ạ, làm trên C càng tốt, nếu không thì các bác cứ hướng dẫn trên asm cũng được, em có thể chèn đoạn mã asm vào trong C.

Cám ơn các bác nhiều !!!

namqn
23-11-2009, 12:00 AM
...
Em cũng đã xem 1 số tài liệu hướng dẫn cách lập trình, người ta có nói là chương trình cho ngắt không nên quá dài. Em nghĩ cũng có thể là chương trình ngắt của em dài quá (em có sử dụng kiểu biến int32 trong đó) nên nó bị lỗi này.

Em muốn hỏi các bác xem có cách nào khắc phục lỗi này được không, em có ý tưởng là sau 1 lệnh, mình có thể xóa ngay dữ liệu trong stack đi, rồi tiếp tục thực hiện lệnh tiếp theo, như vậy sẽ ko bị tràn stack nữa.

Cái khó là em không biết thao tác thế nào với ý tưởng này. Bác nào biết thì hướng dẫn em với ạ, làm trên C càng tốt, nếu không thì các bác cứ hướng dẫn trên asm cũng được, em có thể chèn đoạn mã asm vào trong C
Đúng là chương trình xử lý ngắt không nên quá dài, bạn chỉ cần bật 1 cờ, và kiểm tra cờ đó trong chương trình chính. Nếu cờ báo hiệu cần gọi 1 loạt hàm thì bạn gọi các hàm đó. Không có lý do gì để nhét các lệnh gọi hàm mà bạn đã dùng vào chương trình xử lý ngắt.

Stack của PIC tầm trung là stack phần cứng, chứ không phải là stack phần mềm để bạn có thể dùng lệnh C hay hợp ngữ mà thao tác.

Thân,

pk178
23-11-2009, 12:08 AM
Cám ơn bác đã giúp đỡ !!!

Ý của bác là không dùng ngắt nữa, mà thay vào đó là mình sử dụng 1 hàm con thông thường, rồi quét liên tục (chân RB0) xem nó có thay đổi mức logic không, nếu thay đổi thì nhảy đến chương trình con phải không ạ ?

Nếu như vậy, bác cho em hỏi ý tưởng này có được không ạ : em sẽ dùng ngắt để cho phép chọn chế độ, ứng với mỗi chế độ do người dùng chọn, chương trình ngắt sẽ nhảy đến hàm con tương ứng với chế độ đó, như vậy có được không ạ ?

pk178
23-11-2009, 12:11 AM
À, bác cho em hỏi luôn là cái bộ so sánh trong PIC16F877A, mình có thể đưa điện áp đầu vào tối đa là bao nhiêu ạ ? Em đã tra trong datasheet mà không thấy bác ạ !

namqn
23-11-2009, 07:51 AM
Cám ơn bác đã giúp đỡ !!!

Ý của bác là không dùng ngắt nữa, mà thay vào đó là mình sử dụng 1 hàm con thông thường, rồi quét liên tục (chân RB0) xem nó có thay đổi mức logic không, nếu thay đổi thì nhảy đến chương trình con phải không ạ ?

Nếu như vậy, bác cho em hỏi ý tưởng này có được không ạ : em sẽ dùng ngắt để cho phép chọn chế độ, ứng với mỗi chế độ do người dùng chọn, chương trình ngắt sẽ nhảy đến hàm con tương ứng với chế độ đó, như vậy có được không ạ ?
Ý của tôi là trong chương trình phục vụ ngắt, bạn bật 1 cờ báo hiệu rằng đã có sự kiện ngắt. Ở trong vòng lặp chính của chương trình thì bạn dùng cấu trúc if ... để kiểm tra xem có sự kiện đó hay không, nếu có thì thực hiện các thao tác cần thiết. Làm cách này thì bạn vẫn có thể đáp ứng nhanh với sự kiện, mà không mất thời gian trong phần xử lý ngắt, và đặc biệt là không làm tăng độ sâu khi sử dụng stack.

Ý tưởng của bạn nên sửa lại thành: trong chương trình xử lý ngắt sẽ đặt biến trạng thái ứng với từng chế độ, trong vòng lặp chính của chương trình sẽ kiểm tra giá trị biến trạng thái và gọi hàm tương ứng.

Thân,

pk178
23-11-2009, 08:14 AM
Ý kiến của bác em xin hiểu thế này, không biết có đúng không, mong bác chỉ giáo :

......
- Trình phục vụ ngắt :
+ bật cờ báo hiệu có ngắt xảy ra : INT_FLAG = 1
- Chương trình chính :
...........
While(1){ // tạo vòng lặp vô hạn
+ Nếu INT_FLAG = 1{
......
}
+ Thực hiện các công việc A, B, C, D....
.................
}

Nếu như vậy, rõ ràng em vẫn phải thực hiện tiếp tục các công việc A, B, C cho đến khi kết thúc, khi 1 vòng lặp mới bắt đầu thì em mới thực hiện được cái yêu cầu đối với hàm ngắt. Như vậy thì tốc độ đáp ứng cũng đâu có cải thiện gì ạ ?

Tuy nhiên giải pháp của bác cũng là 1 giải pháp hay, ít nhất là đến bây giờ. Tối qua em đã thử dùng 1 chương trình con bình thường, không có ngắt, cũng phải kiểm tra liên tục xem người dùng có nhấn nút hay không.

Cám ơn bác đã giúp đỡ !!!

namqn
23-11-2009, 11:19 AM
Ý kiến của bác em xin hiểu thế này, không biết có đúng không, mong bác chỉ giáo :

......
- Trình phục vụ ngắt :
+ bật cờ báo hiệu có ngắt xảy ra : INT_FLAG = 1
- Chương trình chính :
...........
While(1){ // tạo vòng lặp vô hạn
+ Nếu INT_FLAG = 1{
......
}
+ Thực hiện các công việc A, B, C, D....
.................
}

Nếu như vậy, rõ ràng em vẫn phải thực hiện tiếp tục các công việc A, B, C cho đến khi kết thúc, khi 1 vòng lặp mới bắt đầu thì em mới thực hiện được cái yêu cầu đối với hàm ngắt. Như vậy thì tốc độ đáp ứng cũng đâu có cải thiện gì ạ ?

Tuy nhiên giải pháp của bác cũng là 1 giải pháp hay, ít nhất là đến bây giờ. Tối qua em đã thử dùng 1 chương trình con bình thường, không có ngắt, cũng phải kiểm tra liên tục xem người dùng có nhấn nút hay không.

Cám ơn bác đã giúp đỡ !!!
Bạn đã hiểu đúng ý tôi. Tốc độ đáp ứng bằng với xử lý trực tiếp từ chương trình phục vụ ngắt là tốt nhất rồi, làm gì có thể xử lý nhanh hơn. Điều được cải thiện ở đây là stack không bị sử dụng quá mức, chính là vấn đề bạn đang gặp phải.

Thân,