PIC16F887 Điều khiển thời gian đóng cắt một led từ PC qua UART

Chào các bạn.

Nay ngồi code cho con PIC16F887 để điều khiển đèn halogen, thực ra chính là điều khiển một chân rồi qua TIP122 và relay để điều khiển đèn thôi (vì dòng tải lên tới 10A).

Mình thấy cách viết hay nên chia sẻ với các bạn. Dùng để lưu trữ luôn.

Để điều khiển thời gian dùng lệnh:

Txyzt# : trong đó: xyzt là thời gian viết theo hệ hexa. Đơn vị là ms

S: stop led

P: play led

Đầu tiền là file UART.c và UART.h có chứa các định nghĩa và thực thi dành cho cổng UART. Tất nhiên có thể áp dụng cho mọi loại PIC16.

// UART.h
//=======================================================================================
#ifndef _UART_H
#define _UART_H
//========================================================================================
#include "pic.h"
#include "sysdef.h"

//========================================================================================
// Declare sosme functions
void UART_Init(unsigned int BaudRate);        // Initialize for UART
void UART_PrChar(unsigned char a);
void UART_PrString(const char* str);
unsigned char UART_Read(void);                // Read data from UART Port
//void UART_detectBaudRate(void);                // Auto detect baud rate
#endif

Tiếp theo là hàm thực thi UART.c

// UART.h
# include "UART.h"
# include "pic.h"
# include "sysdef.h"

//========================================================================================
// Initialize UART
void UART_Init(unsigned int BaudRate){
    unsigned int n;

// Configure BaudRate
    BRGH = 0;                 // Low speed.
    BRG16 = 1;                // 16-Bit Baud Rate Generator - SPBRGH and SPBRG

    // Baudrate = Fosc/[16(n+1)]  => n = ((Fosc/Baudrate)>>4) - 1;  n = SPBRGH: SPBRG;
    n = ((Fosc/BaudRate)>>4) - 1;
    SPBRG = n;
    SPBRGH = n>>8;
// Enable the asyncchronous serial port.
    SYNC = 0 ;                // Asynchronous mode   
    SPEN = 1;                // Serial port enable.
    TRIS_TX = 0;
    TRIS_RX = 1;

//Configure for Transmitter mode.   
    TXEN  = 1;                 // Transmit enable

//Configure for Receiver mode
    CREN = 1;                // Enable the reception

    RCIF = 0;
    RCIE = 1;                // Reception Interrupt Enable
    GIE = 1;                // Global Interrupt Enable
    PEIE = 1;                // Perapheral Interrupt Enable
}   

//=====================================================================================
void UART_PrChar(unsigned char a){
    while(!TRMT);
    TXREG = a;
}   

//=====================================================================================
void UART_PrString(const char* str){
    while(*str)
        UART_PrChar(*str ++);
}   

//=====================================================================================
unsigned char UART_Read(void){
    return (RCREG);
}   

//====================================================================================
// Only avaiable for PIC18
/*
void UART_detectBaudRate(void){
    TXSTA     = 0b00100100;
    RCSTA     = 0b10010000;
    BAUDCON = 0b00001001;
    while(ABDEN){
        if(ABDOVF == 1) ABDOVF = 0;
    };
}
*/

Tiếp theo là sysdef.h dùng để định nghĩa các biến dành cho hệ thống:

// Define some useful values

#define    Fosc    20000000    //  Frequency of Crystal

// Define some temp signals
#define led1        RB7//RD2//RB7

#define    led1_cntL    TMR2    // Led1 counter as 16 bit,
#define led1_cntH    ADRESH

#define    UART_Data    CCPR2H    // UART Data temporary   

// Define 8 bit acc
#define acc1            TMR1L
#define acc2            TMR1H
#define acc3            ANSELH
#define acc4            EEADRL
#define led1_cnt_acc1    CCPR1H
#define led1_cnt_acc2    CCPR1L

#define progress        SSPADD
// Define for UART Module
#define TX            RC6
#define RX             RC7
#
define TRIS_TX        TRISC6
#define TRIS_RX        TRISC7

Tiếp theo là system.h định nghĩa các hàm hệ thống:

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' + 0x0A);
}

Cuối cùng là hàm Main.c là hàm chính:

/*;========================================================
/*; Ten chuong trinh    : Test IO
; Nguoi thuc hien    : Ngo Hai Bac (NOHB)
; Ngay thuc hien    : 27/06/07
; Phien ban            : 1.0       
; Mo ta phan cung    : Dung PIC18F2525/2620/4525/4620 - thach anh 20MHz
; Trinh dich            : HTPIC 18V9.50               
;               
;----------------------------------------------------------------
; Ngay hoan thanh    :
; Ngay kiem tra    :
; Nguoi kiem tra    :
;----------------------------------------------------------------
; Chu thich    :        
;========================================================*/
// Include
# include "pic.h"
# include "sysdef.h"
# include "UART.h"
# include "system.h"

// configuration
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );

// Receiver Interrupt Function
void RxIntFcn(void);
void Timer0IntFcn(void);
// Interrupt Function
void interrupt MyInt  (void) {
    if (RCIE && RCIF){
        RCIF = 0;
        RxIntFcn();   
    };
    if (T0IE && T0IF){
        T0IF     = 0;        // Clear interrupt flag
        TMR0    = 100;
        Timer0IntFcn();
    };
}
// Init function
void System_Init(void);
/*=====================================================================================
    Main function
=====================================================================================*/
void main(){
    System_Init();   
    UART_Init(9600);
    //UART_detectBaudRate();

    while(1);
}

//=====================================================================================
// Implementation of some functions

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 = 0x6F; // 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 = 0x4D;    // 1s = 1000 = 0x03E8
    
;                    led1_cntH = 0x1;
                        break;
                    case '4':           
                        //RB5      = 1;
                        led1_cntL = 0xBC;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x01;
                        break;       
                    case '5':           
                        //RB5      = 1;
                        led1_cntL = 0x2B;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x02;
                        break;
                    case '6':           
                        //RB5      = 1;
                        led1_cntL = 0x9A;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x02;
                        break;
                    case '7':           
                        //RB5      = 1;
                        led1_cntL = 0x09;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x03;
                        break;
                    case '8':           
                        //RB5      = 1;
                        led1_cntL = 0x78;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x03;
                        break;
                    case '9':           
                        //RB5      = 1;
                        led1_cntL = 0xE7;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x03;
                        break;
                    case '0':           
                        //RB5      = 1;
                        led1_cntL = 0xE8;    // 5s = 5000 = 0x1388
                        led1_cntH = 0x03;
                        break;                       
                    default:
                        PORTB   &= 0x80;
                };
            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;
    };
}

// Timer0 interrupt function
void Timer0IntFcn(void){   
    // Control led1   
    led1 = 1;
    if (led1_cntL == 0){

60;       if (led1_cntH == 0)
            led1 = 0;   
        else {
            led1_cntH --;
            led1_cntL --;
        };
    }
    else    led1_cntL--;   
}
// Initialize the system
void System_Init(void){
// Init for ports
    // PortA as output
    OPTION = 0b00000000;
    ADCON1    = 0x07;            /*Configure all ADC pins  to be digital inputs*/
    TRISA    = 0x00;
    PORTA    = 0xFF;

    // PortB as output
    TRISB    = 0x00;
    PORTB    = 0x00;
    // PortD as input
    TRISD   = 0x00;
    TRISD   = 0x00;
// Init for Timer0
    //Init TCON Register
    /*

    T0CS    = 0;            // Internal instruction cycle clock (CLKO)
    TOSE    = 0;
    PSA        = 0;            // Timer0 is assigned. Timer0 clock input comes from prescaler output
    T0PS2   = 1;            // Scale value = 100 -> 32
    T0PS1   = 0;
    T0PS0   = 0;
    */
    OPTION    = 0b00000100;
    // Init timer0
    TMR0    = 100;            //1000 us = 0.2us * 5000 = 0.2us * 32(pre) * 156   
    T0IE    = 1;            // enable Timer0 interrupt
    T0IF    = 0;            // Clear Timer0 interrupt flag

// Init for counters
    led1_cntH = 0;
    led1_cntL = 0;
    led1_cnt_acc1 = 0;
    led1_cnt_acc2 = 0;
    progress      = 0;
}

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

{ 4 comments… add one }
  • Hoang Bac August 18, 2008, 12:12 am

    thank you nhieu lam minh dang rat can cac tai lieu cac lap trinh lien quan den he thong 😆 😆 😆 😆

    Reply
  • KIMCANG March 26, 2009, 11:35 pm

    THANKS BAC HAI NHIEU LAM LAM.NHUNG MA EM CO Y KIEN THE NAY SAO MOT SO TAI LIEU CUA BAC EM LOAD HOAI LA KHONG DUOC DUOC DAN CO VE KHONG TOT.BAC UP TRUC TIEP ANH EM NHAN VAO LINE LA LOAD DUOC NGAY DO PHAI DI LONG VONG MET LAM
    MONG BAC CANG NGAY CANG KHOE DE UP NHIEU TAI LIEU CHO ANH EM
    THANKS
    SEE YOU AGAIN

    Reply
  • Paul January 24, 2013, 10:53 pm

    Anh Bắc có tài liệu lập trình C cho Vi xử lí không share cho em với ạ.
    Em cám ơn anh.

    Reply

Leave a Comment