PIC Vietnam

Go Back   PIC Vietnam > Microchip PIC > Cơ bản về vi điều khiển và PIC

Tài trợ cho PIC Vietnam
Trang chủ Đăng Kí Hỏi/Ðáp Thành Viên Lịch Bài Trong Ngày Vi điều khiển

Cơ bản về vi điều khiển và PIC Những bài hướng dẫn cơ bản nhất để làm quen với vi điều khiển PIC

Trả lời
 
Ðiều Chỉnh Xếp Bài
Old 08-04-2009, 11:49 PM   #1
thaithien
Đệ tử 7 túi
 
Tham gia ngày: Aug 2007
Bài gửi: 213
:
CCS-Chuyển giá trị từ chương trình chính sang chuơng trình ngắt

Mình viết đoạn code như sau để thực hiện ngắt trên port D:
Code:
// INTEXT.C  MPB  10-4-07
// Demo external interrupt
// RB0 low interrupts 
// foregroundoutput count

#include "16F887.h"
#use delay(clock=2000000)

#int_ext
    void isrext()
    {   output_D(255);
        delay_ms(1000);
    }



void main()
{
    int x=10;

    enable_interrupts(int_ext); 
    enable_interrupts(global);
    ext_int_edge(H_TO_L); 

    while(1)
    {   
        output_D(x); 
        x++;
        delay_ms(100);
    }
}

Bây giờ mình muốn chương trình ngắt thực hiện công việc là khi bắt đầu ngắt thì sẽ lấy giá trị hiện thời của x trong chương trình chính và đưa vào chương trình ngắt,mình sửa code lại như sau nhưng chưa chạy được:
Code:
// INTEXT.C  MPB  10-4-07
// Demo external interrupt
// RB0 low interrupts 
// foregroundoutput count

#include "16F887.h"
#use delay(clock=2000000)

#int_ext
    void isrext()
    {   output_C(x);      //muc dich là xuat ra portC giá trị của x hiện thời trong ct chính
        delay_ms(1000);
    }



void main()
{
    int x=10;

    enable_interrupts(int_ext); 
    enable_interrupts(global);
    ext_int_edge(H_TO_L); 

    while(1)
    {   
        output_D(x); 
        x++;
        delay_ms(100);
    }
}
thaithien vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 09-04-2009, 12:22 AM   #2
namqn
Trưởng lão PIC bang
 
Tham gia ngày: Feb 2006
Nơi Cư Ngụ: Tp. HCM, Việt Nam
Bài gửi: 3,025
:
Send a message via Yahoo to namqn
Bạn không nên dùng delay_ms(1000) trong chương trình xử lý ngắt, vì các hoạt động khác trong vòng lặp chính sẽ bị dừng lại cho đến khi trở về từ ngắt, mà trong ngắt bạn lại dừng lại 1000 ms chẳng làm gì cả.

Thân,
__________________
Biển học mênh mông, sức người có hạn.

Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
http://www.picvietnam.com/forum/showthread.php?t=1263
namqn vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 01-05-2009, 10:29 AM   #3
nguyenluong
Đệ tử 2 túi
 
Tham gia ngày: Oct 2008
Bài gửi: 27
:
Trích:
Nguyên văn bởi namqn View Post
Bạn không nên dùng delay_ms(1000) trong chương trình xử lý ngắt, vì các hoạt động khác trong vòng lặp chính sẽ bị dừng lại cho đến khi trở về từ ngắt, mà trong ngắt bạn lại dừng lại 1000 ms chẳng làm gì cả.

Thân,
================================================== ===============
để delay_ms(1000) cũng được có sao đâu. Tùy theo mục đích của mình thôi, hơn nữa trong chương trình này mình chỉ sử dụng một ngắt thôi mà. Đâu sợ ngắt khác xảy ra.
nguyenluong vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 09-04-2009, 01:24 AM   #4
thaithien
Đệ tử 7 túi
 
Tham gia ngày: Aug 2007
Bài gửi: 213
:
Vậy còn vấn đề biến x thì sao hả anh ?Em nghĩ là giá trị x trong chương trình chính đang chạy sẽ lưu vào một địa chỉ nhớ nào đó.làm sao mình đọc nó ra và gán vào cho biết nằm trong chương trình ngắt ?
thaithien vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 09-04-2009, 03:33 AM   #5
namqn
Trưởng lão PIC bang
 
Tham gia ngày: Feb 2006
Nơi Cư Ngụ: Tp. HCM, Việt Nam
Bài gửi: 3,025
:
Send a message via Yahoo to namqn
Trích:
Nguyên văn bởi thaithien View Post
Vậy còn vấn đề biến x thì sao hả anh ?Em nghĩ là giá trị x trong chương trình chính đang chạy sẽ lưu vào một địa chỉ nhớ nào đó.làm sao mình đọc nó ra và gán vào cho biết nằm trong chương trình ngắt ?
Tôi không dùng CCS C nên không rõ biến x trong main sẽ được trình biên dịch xử lý ra sao khi được truy xuất trong chương trình xử lý ngắt, nhưng tôi cho rằng bạn có thể dùng biến toàn cục (nghĩa là đặt biến x ra ngoài main() và isrext() của bạn).

Thân,
__________________
Biển học mênh mông, sức người có hạn.

Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
http://www.picvietnam.com/forum/showthread.php?t=1263
namqn vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 10-04-2009, 10:04 AM   #6
ThaoBinh90
Đệ tử 1 túi
 
Tham gia ngày: Feb 2009
Bài gửi: 19
:
Smile

Trích:
Nguyên văn bởi namqn View Post
Tôi không dùng CCS C nên không rõ biến x trong main sẽ được trình biên dịch xử lý ra sao khi được truy xuất trong chương trình xử lý ngắt, nhưng tôi cho rằng bạn có thể dùng biến toàn cục (nghĩa là đặt biến x ra ngoài main() và isrext() của bạn).

Thân,
- Mình cũng nghĩ vậy đó, nếu khai báo x la biến toàn cục thì ngắt có thể hiểu được đó!
ThaoBinh90 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 04-05-2009, 07:00 PM   #7
nguyenluong
Đệ tử 2 túi
 
Tham gia ngày: Oct 2008
Bài gửi: 27
:
Trích:
Nguyên văn bởi thaithien View Post
Vậy còn vấn đề biến x thì sao hả anh ?Em nghĩ là giá trị x trong chương trình chính đang chạy sẽ lưu vào một địa chỉ nhớ nào đó.làm sao mình đọc nó ra và gán vào cho biết nằm trong chương trình ngắt ?
Bác nghĩ vậy có thể chưa đúng, Nếu x là biến toàn cục thì biến x trong main va trong ngắt là một. Nếu x không phải là biến toàn cục thì khác nhau, tức là như bác nói vậy, x trong chương trình main là khác, khi vô ngắt x này tự lưu lại và x trong ngắt là một biến khác. Khi thoát khỏi ngắt thì nó lại pop giá trị x nảy lưu ra tính tiếp. chào
nguyenluong vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 09-04-2009, 11:12 AM   #8
cskiller
Đệ tử 4 túi
 
Tham gia ngày: Aug 2008
Bài gửi: 89
:
Code:
// INTEXT.C  MPB  10-4-07
// Demo external interrupt
// RB0 low interrupts 
// foregroundoutput count

#include "16F877a.h" 
#fuses HS,NOWDT         
#use delay(clock=12000000)

int x=10;      
      
#int_ext
void isrext()                           
{  
   output_c(x);      //muc dich là xuat ra portC giá tri. cu?a x hie^.n tho+`i trong ct chính
   delay_ms(1000);
}

               
void main()
{   
                                   
    enable_interrupts(global);
     
    set_tris_b(get_tris_b()|0x01);
    enable_interrupts(int_ext);
    ext_int_edge(H_TO_L); 

    while(1)
    {   
        output_d(x);
        x++;
        delay_ms(100);
    }
}
Không có 16F887 nhưng chương trình test với 16F877A thấy OK mà.
Chú ý: Tầm cực biến x để isrext() có thể truy cập. Giá trị trên Port D sẽ thường nhỏ hơn 1 so với Port C vì lệnh x++ thực thi sau lệnh gán output_d(x) (chỉ trừ khi interrupt xảy ra ngay sau lệnh output_d(x) và trước lệnh x++, khả năng ~ 0) nên nếu muốn 2 Port xuất giá trị bằng nhau khi nhấn phím thì chuyển lệnh x++ lên trước.
__________________
Quang báo RG/RGB 6/8/12/16 bits màu
Phone No: 0905.034.086
Email: lmquyen@gmail.com
cskiller vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 10-04-2009, 10:26 AM   #9
bien_van_khat
...Damned...
 
bien_van_khat's Avatar
 
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
:
Trích:
Nguyên văn bởi cskiller View Post
Code:
// INTEXT.C  MPB  10-4-07
// Demo external interrupt
// RB0 low interrupts 
// foregroundoutput count

#include "16F877a.h" 
#fuses HS,NOWDT         
#use delay(clock=12000000)

int x=10;      
      
#int_ext
void isrext()                           
{  
   output_c(x);      //muc dich là xuat ra portC giá tri. cu?a x hie^.n tho+`i trong ct chính
   delay_ms(1000);
}

               
void main()
{   
                                   
    enable_interrupts(global);
     
    set_tris_b(get_tris_b()|0x01);
    enable_interrupts(int_ext);
    ext_int_edge(H_TO_L); 

    while(1)
    {   
        output_d(x);
        x++;
        delay_ms(100);
    }
}
Điều gì sẽ xảy ra nếu ngắt xảy ra khi đang thực hiện biểu thức x++?

Với biến kiểu integer 8 bit, biểu thức x++ có thể được dịch thành mã máy là incf x, 1, tức là thực hiện x++ chỉ trong 1 chu kỳ máy, trong trường hợp này thì chưa có vấn đề.

Nhưng không ai đảm bảo là biểu thức đó sẽ được dịch thành chỉ 1 lệnh. Nếu x là kiểu 16 hoặc 32 bit thì chắc chắn là không thể thực hiện x++ trong 1 chu kỳ máy.

Nếu ngắt xảy ra khi đang thực hiện x++, chuơng trình phục vụ ngắt của bạn lại thay đổi giá trị của x thì sẽ gây lỗi chuơng trình và có thể rất khó phát hiện vì hiếm khi xảy ra.

Để tránh trường hợp này, với những biến dùng chung cho cả chuơng trình chính và chuơng trình con bạn phải khai báo volatile.

VD: volatile int x;
__________________
- Xin đọc trước khi post bài

Xin đặt code trong thẻ [ code ] [ /code ]
bien_van_khat vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 10-04-2009, 11:53 AM   #10
cskiller
Đệ tử 4 túi
 
Tham gia ngày: Aug 2008
Bài gửi: 89
:
Trích:
Nguyên văn bởi bien_van_khat View Post
Điều gì sẽ xảy ra nếu ngắt xảy ra khi đang thực hiện biểu thức x++?

Với biến kiểu integer 8 bit, biểu thức x++ có thể được dịch thành mã máy là incf x, 1, tức là thực hiện x++ chỉ trong 1 chu kỳ máy, trong trường hợp này thì chưa có vấn đề.

Nhưng không ai đảm bảo là biểu thức đó sẽ được dịch thành chỉ 1 lệnh. Nếu x là kiểu 16 hoặc 32 bit thì chắc chắn là không thể thực hiện x++ trong 1 chu kỳ máy.

Nếu ngắt xảy ra khi đang thực hiện x++, chuơng trình phục vụ ngắt của bạn lại thay đổi giá trị của x thì sẽ gây lỗi chuơng trình và có thể rất khó phát hiện vì hiếm khi xảy ra.

Để tránh trường hợp này, với những biến dùng chung cho cả chuơng trình chính và chuơng trình con bạn phải khai báo volatile.

VD: volatile int x;
1. Trong chương trình này, khả năng xảy ra khi đang thực thi x++ là ~0(1 vài lệnh so với delay_ms(100); chẳng thấm vào đâu) và hàm phục vụ ngắt không thực hiện tác vụ write/update biến mà chỉ read giá trị.
2. Việc khai báo volatile cho biết biến x có thể được truy cập, thay đổi giá trị từ nhiều điểm thực thị trong chương trình(nên thường dùng cho các port IO) chứ không đảm bảo việc khi thực hiện x++ sẽ đúng khi có nhiều chương trình cùng thao tác trên x. Một điểm nữa cần để ý là khai báo volatile sẽ giúp compiler sẽ thực hiện thao tác tối ưu đúng(không tự động xóa các biểu thức điều kiện sai) khi gặp biến volatile.
3. Giải pháp critical access đơn giản nhất là:
Code:
disable_interrupts(GLOBAL);  //Đảm bảo không có ngắt nào được thực thi đoạn code tiếp sau lệnh này
x++;     //x co the la so integer 8,16,32 bits
enable_interrupts(GLOBAL);
__________________
Quang báo RG/RGB 6/8/12/16 bits màu
Phone No: 0905.034.086
Email: lmquyen@gmail.com
cskiller vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 10-04-2009, 06:18 PM   #11
bien_van_khat
...Damned...
 
bien_van_khat's Avatar
 
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
:
Trích:
Nguyên văn bởi cskiller View Post
1. Trong chương trình này, khả năng xảy ra khi đang thực thi x++ là ~0(1 vài lệnh so với delay_ms(100); chẳng thấm vào đâu) và hàm phục vụ ngắt không thực hiện tác vụ write/update biến mà chỉ read giá trị.
Không ai dám đảm bảo rằng nó sẽ ko xảy ra, cho dù xác suất là nhỏ, nếu lỗi đã có thể xảy ra thì luôn cần phải tránh.
Dĩ nhiên trong bài toán này, lỗi này ko xảy ra vì x++ chỉ thực hiện trong 1 chu kỳ máy. Và có xảy ra cũng ko gây ra chuyện gì ghê ghớm, chỉ hiện thị sai vài con led.

Trích:
2. Việc khai báo volatile cho biết biến x có thể được truy cập, thay đổi giá trị từ nhiều điểm thực thị trong chương trình(nên thường dùng cho các port IO) chứ không đảm bảo việc khi thực hiện x++ sẽ đúng khi có nhiều chương trình cùng thao tác trên x.
Mình sai chỗ này, ở đây phải dùng cách này
Trích:
3. Giải pháp critical access đơn giản nhất là:
Code:
disable_interrupts(GLOBAL);  //Đảm bảo không có ngắt nào được thực thi đoạn code tiếp sau lệnh này
x++;     //x co the la so integer 8,16,32 bits
enable_interrupts(GLOBAL);
Trích:
Một điểm nữa cần để ý là khai báo volatile sẽ giúp compiler sẽ thực hiện thao tác tối ưu đúng(không tự động xóa các biểu thức điều kiện sai) khi gặp biến volatile.
Mình chưa hiểu ý bạn?
__________________
- Xin đọc trước khi post bài

Xin đặt code trong thẻ [ code ] [ /code ]
bien_van_khat vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 10-04-2009, 08:10 PM   #12
namqn
Trưởng lão PIC bang
 
Tham gia ngày: Feb 2006
Nơi Cư Ngụ: Tp. HCM, Việt Nam
Bài gửi: 3,025
:
Send a message via Yahoo to namqn
Trích:
Nguyên văn bởi bien_van_khat View Post
...
Mình chưa hiểu ý bạn?
Google với cụm từ khóa "volatile in C", một vài link tốt như sau:
http://publications.gbdirect.co.uk/c..._volatile.html
http://www.netrino.com/node/80

Thân,
__________________
Biển học mênh mông, sức người có hạn.

Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
http://www.picvietnam.com/forum/showthread.php?t=1263
namqn vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 29-04-2009, 03:28 PM   #13
bien_van_khat
...Damned...
 
bien_van_khat's Avatar
 
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
:
"The use of volatile is poorly understood by many programmers".
__________________
- Xin đọc trước khi post bài

Xin đặt code trong thẻ [ code ] [ /code ]
bien_van_khat vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Trả lời


Quyền Sử Dụng Ở Diễn Ðàn
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is Mở
Smilies đang Mở
[IMG] đang Mở
HTML đang Tắt

Chuyển đến


Múi giờ GMT. Hiện tại là 07:18 AM.


Được sáng lập bởi Đoàn Hiệp
Powered by vBulletin®
Page copy protected against web site content infringement by Copyscape
Copyright © PIC Vietnam