Tài khoản E-mail miễn phí @ngohaibac.net

Các bạn hãy dành chút thời gian đọc kĩ hướng dẫn sử dụng trước khi dùng.

Phân tích thuật toán: thực hiện lệnh điều khiển từ PC qua RS232

By admin
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Chào các bạn.

Không biết ai đã đọc bài viết của mình PIC16F887 – Điều khiển thời gian đóng cắt một led từ PC qua UART chưa. Trong này, mình có thực hiện đặt thời gian đóng cắt từ PC bằng lệnh với cú pháp.

Txyzt#: trong đó  xyzt là thời gian tính theo hệ hexa.

Đây là đoạn chương trình xử lý ngắt UART:

void RxIntFcn(void){
    UART_Data = UART_Read();
    UART_PrChar(UART_Data);
    // Detect set time command
    // as format: Txy#
    switch (progress){
        case 0:                //Initialize
            if(UART_Data == ‘T’)
                progress = 1;
            else
                progress = 0;
                switch(UART_Data){
                    case ‘1′:
                        //RB6       = 1;
                        led1_cntL = 0×6F; // 1/9 s = 111 ms
                        led1_cntH = 1;
                        break;
                    case ‘2′:
                        //RB6       = 1;
                        led1_cntL = 0xDE; // 2/9
                        led1_cntH = 0;
                        break;               
                    case ‘3′:           
                        //RB5      = 1;
                        led1_cntL = 0×4D;    // 1s = 1000 = 0×03E8
                        led1_cntH = 0×1;
                        break;
                    case ‘4′:           
                        //RB5      = 1;
                        led1_cntL = 0xBC;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×01;
                        break;       
                    case ‘5′:           
                        //RB5      = 1;
                        led1_cntL = 0×2B;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×02;
                        break;
                    case ‘6′:           
                        //RB5      = 1;
                        led1_cntL = 0×9A;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×02;
                        break;
                    case ‘7′:           
                        //RB5      = 1;
                        led1_cntL = 0×09;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×03;
                        break;
                    case ‘8′:           
                        //RB5      = 1;
                        led1_cntL = 0×78;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×03;
                        break;
                    case ‘9′:           
                        //RB5      = 1;
                        led1_cntL = 0xE7;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×03;
                        break;
                    case ‘0′:           
                        //RB5      = 1;
                        led1_cntL = 0xE8;    // 5s = 5000 = 0×1388
                        led1_cntH = 0×03;
                        break;                       
                    default:
                        PORTB   &= 0×80;
                };
            break;
        case 1:                // Received ‘T’ character
            // Determind next state
            if (ishexa(UART_Data) == 1){
                progress = 2;
                // Write data to acc1
                acc1     = ascii2num(UART_Data);
            }
            else{
                UART_PrString(" Command error");
                progress = 0;
            };
            break;
        case 2:                // Received ‘x’ character
            if (ishexa(UART_Data) == 1){
                progress = 3;
                // Write data to acc2
                acc2     = ascii2num(UART_Data);
            }
            else{
                UART_PrString(" Command error");
                progress = 0;
            };
            break;
        case 3:                // Received ‘x’ character
            if (ishexa(UART_Data) == 1){
                progress = 4;
                // Write data to acc2
                acc3     = ascii2num(UART_Data);
            }
            else{
                UART_PrString(" Command error");
                progress = 0;
            };
            break;
        case 4:                // Received ‘x’ character
            if (ishexa(UART_Data) == 1){
                progress = 5;
                // Write data to acc2
                acc4     = ascii2num(UART_Data);
            }
            else{
                UART_PrString(" Command error");
                progress = 0;
            };
            break;
        case 5:
            if (UART_Data == ‘#’){
                progress = 0;
                // Write ‘OK’ statement
                UART_PrString(" Timer is set");
                // Update data from ACC to led1_counter_acc
                led1_cnt_acc1 = (acc1<<4) | acc2;
                led1_cnt_acc2 = (acc3<<4) | acc4;
            }
            else{
                UART_PrString(" Command error");
                progress = 0;
            };
            break;
        default: progress = 0;
            break;
    };

    // On, off command
    switch(UART_Data){
        case ‘P’:        // On led
            // Update led1_counter
            led1_cntH = led1_cnt_acc1;
            led1_cntL = led1_cnt_acc2;
            break;
        case ‘S’:
            // Clear led1_counter content
            led1_cntH = 0;
            led1_cntL = 0;
            break;
    };
}

Thuật toán mình sử dụng rất đơn giản: dùng một biến progress là biến quá trình. Mặc định giá trị này là 0, khi nhận dc đúng kí tự T thì biến sẽ có giá trị = 1. Khi đó, nó sẽ kiểm tra tiếp theo có phải gõ vào là chữ số từ 0 đến 9, và từ A đến F hay không.Mỗi trạng thái, khi nhận đúng đều chuyển từ giá trị string sang giá trị số, ví dụ: kí tự ‘0’ chuyển thành giá trị unsigned char là 1. Xem hàm này trong hàm system.h. Nếu đúng thì progress tiếp tục tăng đến trạng thái kiểm tra tiếp theo, nếu không nó sẽ báo lỗi “Command Error” gửi lên PC.

Tiếp tục, đến cuối cùng khi nhận xong kí tự # thì tức là đã nhận đúng lệnh và thực hiện gán dữ liệu để lấy ra byte cao và byte thấp của giá trị nhập vào.

Đây là hàm system.h

bit ishexa(unsigned char a){
    if ((a >= ‘0′ && a<= ‘9′) || (a>= ‘A’ && a<= ‘F’))
        return 1;
    else return 0;
};

// Convert from ASCII to number
unsigned char ascii2num(unsigned char a){
    if( a >= ‘0′ && a<= ‘9′)
        return (a-’0′);
    else
        return (a-’A’ + 0×0A);
}

Hi vọng phân tích của mình làm các bạn hiểu được cách để thực hiện các lệnh điều khiển từ PC hiệu quả.

Chúc các bạn thành công.

Các bài viết liên quan:

  1. VU posted the following on 4 August, 2008 at 8:42 pm.

    Giúp mình quét led ma trận 8×8 với!Mình không biết làm sao để đưa ra một kí tự cả. Minh dùng quét theo cột. Dùng con atmega 16. Giúp mình với!

    Reply to VU

Leave a reply

:mrgreen: :| :twisted: :arrow: 8O :) :? 8) :evil: :D :idea: :oops: :P :roll: ;) :cry: :o :lol: :x :( :!: :?: