PDA

View Full Version : HTPIC - các chương trình cho PIC6F877A


ngohaibac
12-03-2006, 04:18 PM
Tôi đã viết các bài viết ở Điện tử Việt Nam tại luồng này:
http://dientuvietnam.net/forums/showthread.php?p=14688#post14688

Ngôn ngữ là: HTPIC

Có lẽ bài toán nháy led là bài toán đơn giản và tạo hứng thú cho các bạn học vi điều khiển. Tôi xin mạn phép up chương trình nháy led đơn giản và xin các bạn cho ý kiến là liệu có thể tối ưu chương trình này đến mức nào nữa?


Miêu tả phần cứng: nối các chân của PORTD với các 8led. Các chân còn lại của led nối với một con trở hạn dòng 330Ohm, sau đó nối với GND.


Đây là sơ đồ nguyên lý:

http://i36.photobucket.com/albums/e46/ngohaibac/IMG/PVN_00009.gif

Hình 1: Nháy 8led rất đẹp :D.

Phần mềm: dùng HTPIC.

Hiện tuợng: các bạn chạy thử xem thế nào :D

Giải pháp: có 2 giải pháp là dùng ngắt hoặc dùng delay.

Chương trình đầu là dùng delay:

Sau đây là chương trình:

#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );
//================================================== ==============
//== ham Delay doi so la so miligiay can gay tre
void delayMS(unsigned int time){
while(time--){
TMR0 = 6;
T0IF = 0; // xoa co ngat
while(!T0IF);
};
}

// == Ham khoi tao cho chip PIC16F877A
void init(void){
// Khoi tao I/O cho cac port
ADCON1 = 0x07; // PortA dung la I/O Port
TRISA = 0xFF; // Port A as input
TRISB = 0xFF;
TRISC = 0xFF;
TRISD = 0x00;// PortD as output

// Khoi tao cho cac thanh ghi
OPTION = 0x00; // dung prescaler cho timer0 voi ti le la 1:2
}

// Chuong trinh chinh
void main(void){
unsigned char i;
init();
while(1){
for(i = 0;i<8;i++){
PORTD = (1<<i) + (1<<(7-i));
delayMS(5000);
};
};
}

Câu lênh PORTD = (1<<i) + (1<<(7-i)); là dùng toán tử dịch bít.

File gửi kèm có 2 file: PJ1.c và PJ2.c . PJ1.C là chương trình dùng delay, PJ2 là dùng ngắt.

Xin mọi người cho ý kiến.

ngohaibac
12-03-2006, 04:18 PM
Đây là chương trình dùng ngắt timer0.

#include<pic.h>

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

//================================================== ==============
// Hàm ng?t Timer0
void interrupt inter0(void){
static unsigned char i;
static unsigned int counter; // bien dem su kien ngat timer0
if(T0IF){ // neu co ngat Timer0 xay ra
++ counter;
if(counter == 500){
PORTD = (1<<i) + (1<<(7-i));
++i;
if(i==8) i=0;
counter = 0;
};
TMR0 = 6;
T0IF = 0 ; // xoa co ngat, cong viec khong the thieu sau ham ngat
};
}

// == Ham khoi tao cho chip PIC16F877A
void init(void){
// Khoi tao I/O cho cac port
TRISD = 0x00;// PortD as output

// Khoi tao cho cac thanh ghi
OPTION = 0x00; // dung prescaler cho timer0 voi ti le la 1:2

// Khoi tao cho ngat Timer0
GIE = 1; // cho phep ngat toan cuc
T0IE = 1; // cho phep ngat timer0
T0IF = 0; // xoa co ngat
TMR0 = 6; // khoi tao
}

// Chuong trinh chinh
void main(void){
init();
while(1); // de con tro PC khong nhay lung tung,con lam gi thi lam :D
}

Thuật giải của chương trình dùng ngắt đó là: dùng một biến tĩnh kiểu static để đếm số lần xuất hiện ngắt timer0.

Trong chương trình này mình sau 500 ngắt timer0 thì mới quét led1 lần.

Ngoài ra cũng dùng thêm biến static i để biết được đang quét led nào. Do đó dùng ngắt sẽ tiện hơn nhiều. Và dùng đếm sự kiện ngắt thì ta có thể không cần dùng Prescaler với tỉ lệ quá cao, tránh được sai số nhiều.

Không biết mọi người có ý kiến thế nào?

ngohaibac
12-03-2006, 04:21 PM
Tiếp theo tôi xin đưa cho mọi người xem một chương trình của tui không biết liệu nó đã tối ưu chưa? Đã hiệu quả chưa?

Mô tả phần cứng: có 4 led 7 thanh. Các chân của PORTD 7->1 nối với các chân a->g của led7. Các chân RA5 đến RA3 nối vào cực bazơ của con uA1015 lần lượt nối với các cực Anot của 4 led.


Đây là sch: vì to quá nên cắt thành 2 nhìn cho rõ:

http://i36.photobucket.com/albums/e46/ngohaibac/PIC16F877A/PVN_00012.gif
http://i36.photobucket.com/albums/e46/ngohaibac/PIC16F877A/PVN_00013.gif

Hình 2: Quét led 7 thanh.

Yêu cầu của chương trình là: hiển thị ra 4 led các giá trị tăng dần từ 0000 đến 9999 sau đó lại quay lại.

Chương trình này lấy phần giải mã của anh 4MD. chương trình của anh ấy dùng cả delay. Nhưng tôi nghĩ là khi dùng ngắt rùi thì dùng delay làm gì cho phí. Do đó việc dùng ngắt làm cho ta đỡ tốn thời gian làm những việc linh tinh.

Các bạn cho ý kiến về giải thuật này.

#include<pic.h>
const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};

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

//------------------------------------Interrupt
void interrupt MyInt(void){
static int counter1,counter2;
// counter1 dem so lan timer0 tran
// counter2 dem so lan led duoc quet
static unsigned int number;
static unsigned int a[4]={0,0,0,0};
static unsigned char j;
if(T0IF){
++counter1;
if( counter1 == 500){
counter1 = 0;
PORTD = 0xFF;
PORTA = 0xFF - (1<<(5-j));// bat mot led
PORTD = Font[a[j]];
if(++j==4) {
j=0;
++counter2;
};
};
if(counter2 == 500){
++number;
if(number>9999) number= 0;
counter2 = 0;
a[3] = number/1000;
a[2] = (number/100)%10;
a[1] = (number/10)%10;
a[0] = number%10;
};
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
};
}

//------------------------------------init
void init(void)
{
//-------------------------init for PORTs
OPTION = 0b00000000;
ADCON1 = 0b00000111;
TRISA = 0b00000000;
TRISB = 0b11111111;
TRISC = 0b11111111;
TRISD = 0b00000000;
TRISE = 0b11111111;
//-------------------------init for interrupt
GIE = 1;
T0IE = 1;
TMR0 = 6;
}

//------------------------------------MAIN
void main(){
init();
while(1); // Trong này làm gì thì làm
}


Anh 4MD cho ý kiến với em luôn.

Chương trình của mình có cái hay là khi bạn vừa dùng ngắt Timer0 để quét led bạn vừa có thể tận dụng nó để làm việc khác nữa như đếm số lần quét hoặc là delay để làm cái gì đó.

Cái này giống kiểu tiết kiệm chân vi điều khiển vậy :D. Dưới đây có file gửi kèm là 3 file .c của 3 bài trên.

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

chuabietgi
25-03-2006, 12:35 PM
Cho tớ hỏi tí!
Bác dùng phần mềm gì để vẽ mạch vậy?Có free ở đâu không ?Cảm ơn!

linhnc308
26-04-2006, 04:18 AM
a[3] = number/1000;
a[2] = (number/100)%10;
a[1] = (number/10)%10;
a[0] = number%10;


Hàm tách số chục trăm đơn vị này Bắc nên viêt thành một hàm riêng : tach_so(int x)
Bởi hàm này hay phải gọi đến trong CT quét LED 7 hay nhièu CT khác.

ngohaibac
26-04-2006, 08:31 AM
OK, mình xin thay đoạn chương trình đó bằng cách gọi hàm:

Convert(a,4,number);

Với hàm Convert được khai báo và định nghĩa ở trên hàm MyInt như sau:

// ========== Ham chuyen doi
void Convert(unsigned char *a,unsigned char index, unsigned int number){
unsigned char i;
for(i=0;i< index; i++){
*(a+i) = number%10;
number = number/10;
};
}

Các bạn đổi lại kiểu dữ liệu của mảng a trong chương trình lại thành kiểu Unsigned char.

Đoạn code đã được test bằng phần cứng.Đảm bảo thay thế đúng.

Mình xin đưa lại code mới:

/*;================================================ ========
; Ten chuong trinh : Quet 4led 7 thanh
; Nguoi thuc hien : Ngo Hai Bac (NOHB)
; Ngay thuc hien : 12/04/06
; Phien ban : 2.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; 4 led 7 anot chung, cac catot noi voi PORTD, 4 chan anot noi voi cuc E trans A1015
; cuc B cua trans noi voi chan 7->5 cua PORTA
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich :
;================================================= =======*/
#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );

const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};

// ========== Ham chuyen doi
void Convert(unsigned char *a,unsigned char index, unsigned int number){
unsigned char i;
for(i=0;i< index; i++){
*(a+i) = number%10;
number = number/10;
};
}

//===== hàm khởi tạo
void interrupt MyInt(void){
static int counter1,counter2;
// counter1 dem so lan Timer0 tran
// counter2 dem so lan ca 4 led7 thanh duoc quet
static volatile unsigned int number;
static volatile unsigned char a[4]={0,0,0,0};
static volatile unsigned char j; // bien dem kiem tra xem led nao duoc quet
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
++counter1;
if( counter1 == 3){
counter1 = 0;
PORTD = 0xFF;
PORTA = 0xFF - (1<<(5- j)) ;
PORTD = Font[a[j]];
if(++j==4) {
j=0;
++counter2;
};
};
if(counter2 == 200){
if(++number>9999) number= 0;
counter2 = 0;
Convert(a,4,number);
};
};
}

//------------------------------------init
void init(void)
{
//-------------------------init for PORTs
OPTION = 0b00000000;
ADCON1 = 0b00000111;
TRISA = 0b00000000;
TRISB = 0b11111111;
TRISC = 0b11111111;
TRISD = 0b00000000;
PORTD = Font[0];
TRISE = 0b11111111;
//-------------------------init for interrupt
GIE = 1;
T0IE = 1;
TMR0 = 6;
}

//------------------------------------MAIN
void main(){
init();
while(1);
}

// ============== Hết code




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

linhnc308
26-04-2006, 11:31 AM
hay. Mình rất khoái lập trình C. Hồi trước làm AT toàn xài ASM, từ khi biết keil, toàn xài cái này thôi, chỉ khi nào có yêu cầu của khách mình mới viết bằng ASM. Viết bằng C cho nó nhanh. Nhưng minh vẫn thấy viết bằng ASM là nghệ thuật hơn cả. Tuy no hơi dài nhưng phải nói là hay, khi ta giải quyết đc những thuật toán đk...phải nói là hay...
Thực tế thì nên dùng C

ngohaibac
28-04-2006, 08:19 AM
Đây là chương trình khi PC gửi dữ liệu đến PIC thì PIC sẽ phản hồi lại kí tự mà nó đã nhận được. Là một phần trong bài tập lớn của tôi nên tôi sẽ post dần lên cho anh em tham khảo và cho ý kiến về độ tối ưu của chương trình.

/*================================================= =======
; Ten chuong trinh : giao tiep USART voi PC, nhan duoc thi hien thi lai
; Nguoi thuc hien : ngohaibac
; Ngay thuc hien :
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; chan RC7/TX noi voi chan R1OUT cua MAX232
; chan RC6/RX noi voi chan T1IN cua MAX232
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich : Chuong trinh dung giao tiep USART

;================================================= =======*/
#include<pic.h>

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

// ham init - khoi tao
void initUART(void){
// Khoi tao cho USART
TRISC = TRISC | 0b11000000; // Bit 7,6 la RX va TX phai la Input
SPEN = 1 ; // Enable Serial Port communication.
SYNC = 0; // che do khong dong bo Asynchronous
// cho che do truyen
TXEN = 1; //enable truyen
TX9 = 0 ; // chon che do 8 truyen bit du lieu
BRGH = 1; // High - speed
SPBRG = 129; //Baud = 9600; voi HS, Baud Rate = Fosc/(16(X+1))
TXIE = 0; // khong dung ngat Truyen
// Che do nhan du lieu
RCIE = 1; // dung ngat nhan
PEIE = 1; // cho phep ngat ngoai vi
GIE = 1; // cho phep ngat toan cuc
RX9 = 0; // nhan 8 bit
CREN = 1; // lien tuc nhan du lieu; = 0 k lien tuc nhan du lieu

}


// ham truyen du lieu 1 ký tự
void putch(unsigned char byte)
{
/* output one byte */
while(!TXIF); /* set when register is empty */
// continue;
TXREG = byte;
}

void init(void){
initUART();

}
// ham ngat
void interrupt MyInt(void){
unsigned char temp;
if(RCIF){ // Neu co ngat nhan du lieu noi tiep
temp = RCREG;
RCIF = 0; // Xoa co ngat RCIF
putch(temp);
};
}

// ham chinh
void main(void){
//unsigned char a[] =" anh yeu em nhieu lam, em biet k?";
//unsigned char i = 0;
init();
//for(i= 0; i<33; i++) putch(a[i]);
//for(i= 0; i<10; i++) putch(i+48);
while(1);
}


Chương trình này chỉ đơn giản là một ví dụ về truyền nhận dữ liệu còn nếu các bạn muốn truyền, nhận một sâu thì các bạn phải dùng Timeout cho nó để chống mất dữ liệu như sự cố đường dây mà PIC nhà ta vẫn chờ mỏi cả cổ mà vẫn k nhận được hết dữ liệu mà nó cần thì chết :D.

Chương trình đã được test và chạy ngon lành.

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

ngohaibac
02-05-2006, 01:42 AM
Có lẽ chương trình hiển thị số lên led7 đoạn đã được mịnh viết bên dientuvietnam.net nên sẽ không viết lại nữa nha. Nhưng máy mình không vào được site này. Nên đành post lên bên này vậy.

Sau đây là chương trình đếm xung từ chân RC1/T1OSI/CCP2 để hiển thị lên 4led 7 thanh. Một chương trình cũng rất đơn giản.Xin mời các bạn xem và cho ý kiến về chương trình này:

/*;================================================ ========
; Ten chuong trinh : Quet 4led 7 thanh
; Nguoi thuc hien : Ngo Hai Bac (NOHB)
; Ngay thuc hien :
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; 4 led 7 anot chung, cac catot noi voi PORTD, 4 chan anot noi voi cuc E trans A1015
; cuc B cua trans noi voi chan 7->5 cua PORTA
; Xung ngoai duoc cho vao chan RC1/T1OSI/CCP2
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich :
;================================================= =======*/
#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );

const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};


// Chuyen doi
void Convert(unsigned char *a,unsigned char index, unsigned int number){
unsigned char i;
for(i=0;i< index; i++){
*(a+i) = number%10;
number = number/10;
};
}

//===== Ham khoi tao
void interrupt MyInt(void){
static volatile unsigned int counter1,counter2;
// counter1 dem so lan Timer0 tran
// counter2 dem so lan ca 4 led7 thanh duoc quet
static volatile unsigned int number;
static volatile unsigned char a[4]={0,0,0,0};
static volatile unsigned char j; // bien dem kiem tra xem led nao duoc quet
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
++counter1;
if( counter1 == 3){
counter1 = 0;
PORTD = 0xFF;
PORTA = 0xFF - (1<<(5- j)) ;
PORTD = Font[a[j]];
if(++j==4) {
j=0;
++counter2;
};
};
if(counter2 == 2000){
number = (TMR1H << 8) | TMR1L;
TMR1ON = 0 ; // ngung Timer1
TMR1H = TMR1L = 0;
TMR1ON = 1 ; // bat lai Timer1
if(number>9999) number= 0;
counter2 = 0;
Convert(a, 4, number);
};
};
}

//------------------------------------init
void init(void)
{
//================= init for PORTs
OPTION = 0b00000000;
ADCON1 = 0b00000111;
TRISA = 0b00000000;
TRISB = 0b11111111;
TRISC = 0b11111111;
TRISD = 0b00000000;
PORTD = Font[0];
TRISE = 0b11111111;
//================ Khoi tao cho Timer0
GIE = 1;
T0IE = 1;
TMR0 = 6;

// ========= Khoi tao cho dem Timer1
TMR1CS = 1; // Timer1 hoat dong o che do Counter Mode
T1SYNC = 1; // TMR1 hoat dong o che do dem khong dong bo
T1OSCEN = 1; // Dem xung tu chan RC1/T1OSI/CCP2
T1CKPS1 = T1CKPS0 = 0; // Chon Prescaler = 1:1
TMR1H = TMR1L = 0;
TMR1IE = 0; // Khong dung ngat Timer1
TMR1ON = 1; // Bat Timer1

}

//------------------------------------MAIN
void main(){
init();
while(1);
}
// ============= Kết thúc

Chúc mọi người thành công.

ngohaibac
02-05-2006, 01:47 AM
Đây là chương trình điều chế xung PWM trên chân RC2/CCP1 và đếm xung từ chân RC1/T1OSI/CCP2 hiển thị lên 4led7 thanh. Mình dùng Encoder 100 lỗ mượn của bạn :D.

#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );

const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};


// Chuyen doi
void Convert(unsigned char *a,unsigned char index, unsigned int number){
unsigned char i;
for(i=0;i< index; i++){
*(a+i) = number%10;
number = number/10;
};
}

//===== Ham khoi tao
void interrupt MyInt(void){
static volatile unsigned int counter1, counter2, counter3;//, counterTimer1;
unsigned int temp;
// counter1 dem so lan Timer0 tran
// counter2 dem so lan ca 4 led7 thanh duoc quet
static volatile unsigned int number;
static volatile unsigned char a[4]={0,0,0,0};
static volatile unsigned char j,k; // bien dem kiem tra xem led nao duoc quet
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
++counter1;
if( counter1 == 5){
counter1 = 0;
PORTD = 0xFF;
PORTA = 0xFF - (1<<(5- j)) ;
PORTD = Font[a[j]];
if( j==2) RD0= 0;
if(++j==4) j=0;
};
if(++counter2 == 200){
number = (TMR1H << 8) | TMR1L;
// gia tri toc do trong 1s = number * 1000/(100 * counter2 ) (vong/s)
number = number * 5 ; //= number *0.0 5 vong/s => * 5vong/s de hien thi len 4led
TMR1ON = 0 ; // ngung Timer1
TMR1H = TMR1L = 0;
TMR1ON = 1 ; // bat lai Timer1
if(number>9999) number= 0;
counter2 = 0;
Convert(a, 4, number);
};
if(++counter3 == 1000){
k = 70;
counter3 = 0;
temp = 4* (PR2 + 1) * k/100;
CCPR1L = temp>>2;
CCP1Y = temp - ((temp>>1)<<1);//temp%2;
CCP1X = (temp>>1)%2;
//k += 10; // tang 10%
//if( k > 100) k=0;
};
};
}

//------------------------------------init
void init(void){

//===== init for PWM
// PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PR2 = 82; // Tan so = 15 KHz, TMR2 Prescaler Value = 4
// PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
// => CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
CCPR1L = 0;
TRISC2 = 0; // RC2 la output
RC2 = 1;
T2CON = 0b00000101; // Timer2 on, TMR2 Prescaler Value = 4
CCP1CON = 0b00001100; // CCP1 hoat dong trong che do PWM

//================= init for PORTs
OPTION = 0b00000000;
ADCON1 = 0b00000111;
TRISA = 0b00000000;
TRISD = 0b00000000;
PORTD = Font[0];

//================ Khoi tao cho Timer0
GIE = 1;
T0IE = 1;
TMR0 = 6;

// ========= Khoi tao cho dem Timer1
TMR1CS = 1; // Timer1 hoat dong o che do Counter Mode
T1SYNC = 1; // TMR1 hoat dong o che do dem khong dong bo
T1OSCEN = 1; // Dem xung tu chan RC1/T1OSI/CCP2
T1CKPS1 = T1CKPS0 = 0; // Chon Prescaler = 1:1
TMR1H = TMR1L = 0;
TMR1IE = 0 ; // Khong dung ngat Timer1
TMR1ON = 1; // Bat Timer1
}

//------------------------------------MAIN
void main(){
init();
while(1);
}
// == Kết thúc


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

ngohaibac
02-05-2006, 01:52 AM
Chương trình sau nhận lệnh từ PC truyền xuống. Các bạn dựa vào cấu trúc chương trình có thể tự lập cho mình chương trình để làm. Đây là một phần nhỏ trong chương trình thiết kế bộ PID điều khiển động cơ một chiều 12V của tôi:

/*================================================= =======
; Ten chuong trinh : giao tiep USART voi PC, nhan duoc thi hien thi lai
; Nguoi thuc hien : ngohaibac
; Ngay thuc hien :
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; chan RC7/TX noi voi chan R1OUT cua MAX232
; chan RC6/RX noi voi chan T1IN cua MAX232
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich : Chuong trinh dung giao tiep USART

;================================================= =======*/
#include<pic.h>

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

// ham init - khoi tao
void initUART(void){
// Khoi tao cho USART
TRISC = TRISC | 0b11000000; // Bit 7,6 la RX va TX phai la Input
SPEN = 1 ; // Enable Serial Port communication.
SYNC = 0; // che do khong dong bo Asynchronous
// cho che do truyen
TXEN = 1; //enable truyen
TX9 = 0 ; // chon che do 8 truyen bit du lieu
BRGH = 1; // High - speed
SPBRG = 129; //Baud = 9600; voi HS, Baud Rate = Fosc/(16(X+1))
TXIE = 0; // khong dung ngat Truyen
// Che do nhan du lieu
RCIE = 1; // dung ngat nhan
PEIE = 1; // cho phep ngat ngoai vi
GIE = 1; // cho phep ngat toan cuc
RX9 = 0; // nhan 8 bit
CREN = 1; // lien tuc nhan du lieu; = 0 k lien tuc nhan du lieu

}

// Chuyen doi
void Convert(unsigned char *a,unsigned char index, unsigned int number){
unsigned char i;
for(i=0;i< index; i++){
*(a+i) = number%10;
number = number/10;
};
}

// ham truyen du lieu
void putch(unsigned char byte)
{
/* output one byte */
while(!TXIF); /* set when register is empty */
// continue;
TXREG = byte;
}

// ==== Ham ghi len tren mot gia tri cua so co 4 chu so
void puts(unsigned int number){ // truyen 4 so cua number
unsigned char i;
unsigned char a[] = {0,0,0,0};
Convert(a,4,number);
for(i= 0;i<2;i++) putch(a[i]+48);
putch(0x2C);
for(i= 2;i<4;i++) putch(a[i]+48);
putch(0x20);
}

// ======= Ham ghi len tren mot vector gom 4 phan tu
void putsVector(unsigned char *a,unsigned char n){
unsigned char i;
for(i = 0;i<n;i++) putch(a[i]);
}


// Ham khoi tao chung
void init(void){
initUART();
//================ Khoi tao cho Timer0
GIE = 1;
T0IE = 1;
TMR0 = 6;

}
// ham ngat
void interrupt MyInt(void){
unsigned char temp, i,j;
static volatile unsigned char counter4, allow; // temp: bien dem nhan,allow: cho phep nhan du lieu
static volatile unsigned char K[17];
static volatile unsigned char Kp;
static volatile unsigned char Ki;
static volatile unsigned char Kd;
static volatile unsigned char n;
//Kp, Ki, Kd la tham so PID, n la toc do
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
};
if(RCIF){ // Neu co ngat nhan du lieu noi tiep
temp = RCREG;
RCIF = 0; // Xoa co ngat RCIF
switch(temp){
case 'B': // === Bat dau cho dong co chay
putch('B'); allow = 0;
break;
case 'K': // === Tat dong co
putch('K'); allow = 0;
break;
case 'A': // === Nhap cac gia tri cho Kp,Ki,Kd
putch('A');
allow = 1; // chuyen sang nhap cho cac tham so cua mang.
break;
};
if (allow){
K[counter4++] = temp;
if(counter4 == 17) {
allow = 0;
putsVector(K,17);
};
};
};
}

// ham chinh
void main(void){
//unsigned char a[] =" anh yeu em nhieu lam, em biet k?";
unsigned char i = 0;
init();
//for(i= 0; i<33; i++) putch(a[i]);
//for(i= 0; i<10; i++) putch(i+48);
while(1);
}

Chương trình này và 2 chương trình ở trên đều được test và chạy ngon lành.

Chúc mọi người thành công.

totite
21-07-2006, 01:03 PM
Mình có viết một chương trình cho PIC6F88 bằng HT-PIC 805PL2, không hiểu sao trình biên dịch lại bắt đầu chương trình tại địa chỉ 07C0h chứ không phải từ 0000h? Mong các bác chỉ giúp em nhé.

1: #include <pic.h>
2: __CONFIG(INTIO & PWRTEN & BORDIS & WDTDIS & MCLRDIS & LVPDIS );
3:
4:
5:
6: #define R1 0x20;
7: #define R2 0x21;
8: void delayms(int n);
9: void init (void);
10:
11: void delayms(int n)
12: {
13: while(n--)
7C0 2FC6 GOTO 0x7c6
7C6 1283 BCF 0x3, 0x5
7C7 1303 BCF 0x3, 0x6
7C8 0820 MOVF 0x20, W
7C9 1903 BTFSC 0x3, 0x2
7CA 03A1 DECF 0x21, F
7CB 03A0 DECF 0x20, F

typhn
14-08-2006, 12:44 AM
Chào các bác.Em mới học về Pic.Mong các bác chỉ giáo
Em dùng Htpic.
Em viết 1 chương trình đơn giản sử dụng timer0.
Nhưng chả hiểu tại sao thời gian delay ko chính xác(em mô phỏng bằng proteus).
Em delay 1 giây mà mô phỏng chạy những 15 giây(sai số lớn quá)
Mà ko hiểu tại sao lệnh while(1) lại ko lặp lại.Khi đèn chạy được 1 chu kỳ thì nó tắt luôn chứ ko lặp lại.
các bác xem giúp em với


//================================================== ======
//Bai toan phanh xe.Phanh duoc noi vao RB0
//khi phanh thi RB0 o muc thap
//binh thuong RB0 o muc cao
//co 8 led o RD8 den RD0 se sang theo quy luat(khi phanh)
//10000000,01000000...00000001,11111111,00000000
//sau do lap lai neu chua nha phanh
//thoi gian delay la 1 giay
//thach anh 20 Mhz

//================================================== ======
#include<pic.h>
#define out PORTD
__CONFIG(HS & PWRTEN & BOREN & LVPDIS &WDTDIS );
void DL(unsigned int giay);
//--------------------------------------------------------------------------------------------------
const unsigned char a[]={0b10000000,0b01000000,0b00100000,0b00010000,0b00 001000,0b00000100,0b00000010,0b00000001,0b11111111 ,0b00000000};
//================================================== ======
void main()
{
unsigned char i;
TRISB = 0b11111111; //Dinh nghia cong B la INPUT
RBPU =0; //co dien tro trong keo len nguon
TRISD = 0b00000000;
i=0;
while(1)
{
if(RB0==0) //nhan phanh
{
out=a[i];
i=i+1;
DL(25000); //delay 1giay
if(i==11) i=0;
}
else
{
out=0;
i=0;
}
}
}

//------------------------------------------------------------------------
void DL(unsigned int giay)
{
while(giay--)
{
//delay 40 microgiay
PSA=1; //bo chia dung cho wdt
T0CS=0; //dung dem thoi gian
TMR0=56;
while(!TMR0IF);
TMR0IF=0;
}
}
//=============================THE END===========================

typhn
14-08-2006, 06:09 PM
Hình như Picvietnam ko mặn mà với Htpic lắm.
Em sang bên dientuvietnam hỏi vậy

lep
18-08-2006, 02:27 PM
sao minh chạy thu chuong trình đơn giản cho một led tắt mot giây sáng 1 giay tải về nạp pic 877a chạy thử mà không dược nhân dịp cho minh hỏi co chuong trình nào viết ASM rồi chuyển sang C còn C chuyển qua ASM minh biết rồi tại vì mình mới học pic minh không dùng ASM mà đi thẳng vào viết C cho pic trên diển dàn thì bày ASM nhiều

namqn
18-08-2006, 07:38 PM
sao minh chạy thu chuong trình đơn giản cho một led tắt mot giây sáng 1 giay tải về nạp pic 877a chạy thử mà không dược nhân dịp cho minh hỏi co chuong trình nào viết ASM rồi chuyển sang C còn C chuyển qua ASM minh biết rồi tại vì mình mới học pic minh không dùng ASM mà đi thẳng vào viết C cho pic trên diển dàn thì bày ASM nhiều
Cho đến thời điểm này tôi vẫn chưa thấy có phần mềm nào có khả năng chuyển asm thành C.

Thân,

moutainBK
14-10-2006, 09:50 AM
Các bác giúp em với!!!
EM đã cài MPLAB 7.42 và HT PIC 9.50,các bác bảo HT PIC tự nhúng vào MPLAB khi cài nó phải ko?
Bây giờ em soạn file .C trong MPLAB,em muốn biên dịch nó sang file .HẼ cũng trong môi trường MPLAB(sử dụng HT PIC để biên dịch ) thì phải làm cách nào?
Mong các bác trả lời sớm nha
EM cảm ơn nhiều!!!!!!!!

ngohaibac
05-01-2007, 03:17 PM
Bạn muốn biên dịch file .c của bạn thì bạn phải gắn nó vào trong một Project nhé.

Đầu tiên bạn tạo một Project rùi Add file đó vào rùi biên dịch, thế là xong. Mình cài bản HT PIC 9.50 nhưng không biên dịch được và báo lỗi ở file PICC.exe nên đành quay lại dùng bản 8.05PL2.

Bạn chỉ cần cài bản 8.05 dùng ngon lành.
http://www.picvietnam.com/forum//showthread.php?t=31

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

ngohaibac
05-01-2007, 03:54 PM
Sau đây mình copy một số bài bên dientuvietnam.net sang đây và trả lời từng câu hỏi mà các bạn hỏi nhé.

Rảnh rỗi ngồi viết chương trình hiển thị led7 thanh chơi chơi. Ở đây em chỉ dùng 1 led thôi cho đơn giản. Còn việc quét led đã viết ở các bài trước rùi :D.

Đây là sơ đồ nguyên lý:
http://i36.photobucket.com/albums/e46/ngohaibac/PVN_00016.gif

Tiếp theo là chương trình bằng HTPIC:

#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );

// bộ font cho led7
const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};
void init(void)
{
//-------------------------init for PORTs
OPTION = 0b00000000; // dùng Prescaler với k= 1:2
TRISD = 0b00000000;
TRISE = 0b11111111;
PORTD = Font[0] ; // ban đầu cho hiển thị số 0
//-------------------------init for interrupt vầ timer0
GIE = 1; // cho phép ngắt toàn cục
T0IE = 1; // cho phép ngắt timer0
TMR0 = 6; // đặt giá trị đầu cho TMR0
}

void interrupt MyInt(void){
static int counter; // biến đếm sự kiện ngắt timer
static unsigned char i; // biến đếm số đang hiển thị trên led
if (T0IF & T0IE){ // nếu có ngắt
T0IF = 0 ;
TMR0 = 6;
++ counter;
if( counter == 1000){ // cứ 1s thì hiển thị hiển thị tiếp
counter = 0 ; // reset lại bộ đếm
PORTD = Font[i++];
if( i ==10) i = 0;
};
};
}

void main(){
init();
while(1);
}

Chương trình trên cực kỳ đơn giản song chỉ có một câu lệnh cần chú ý là:
if (T0IF & T0IE){
vì timer0 tự chạy nên cờ T0IF liên tục set lên khi đó nếu không phải là ngắt timer0 mà là một ngắt khác xảy ra. Khi đó trong hàm ngắt chương trình sẽ thử điều kiện T0IF = = 1 sẽ đúng. Nếu chúng ta chỉ dùng là if (T0IF) thì tất nhiên là điều kiện thử đúng và sẽ thực hiện chương trình trong if .

Nếu lúc đó ta đã disable ngắt timer0 mà giờ nó lại thực hiện chương trình trong timer0 thì chương trình chạy quá sai rùi. Đây là chú ý của anh BA :D. Nếu không nhận ra thì có khi sai nhiều đó :D. Khi chúng ta viết chương trình ngắt trong ngắt thì sẽ thấy điều này :D.

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

ngohaibac
05-01-2007, 03:56 PM
Bài tiếp theo tôi đã làm, đã test rồi nhưng hôm này con PIC nó bị "ốm" nên không test được.

Đã vậy 3 ngày không được vào diễn đàn vì bọn hack DDOS thấy nhớ quá. Nên vào một cái là up ngay chương trình về ADC cho bà con xem :D. Bạn nào test luôn lại cái và báo lại kết quả cho mình luôn nha.

Phần cứng: Biến trở 10k mắc vào AN0. Đo áp biến đổi ADC hiển thị lên 4 con led7

Đây là schematic:

http://i36.photobucket.com/albums/e46/ngohaibac/PIC16F877A/PVN_00017.gif
http://i36.photobucket.com/albums/e46/ngohaibac/PIC16F877A/PVN_00018.gif

Hình 3: Chuyển đổi ADC, hiển thị LED7 segment.

Loại PIC: 16F877A

Thuật giải là cứ sau mỗi thời gian trích mẫu thì lại bắt đầu chuyển đổi ADC luôn. Khi có ngắt AD thì lưu giá trị vào số number. Còn quét led thì liên tục quét.
Ở đây mình tạo ra một timer0 1ms. Thời gian trích mẫu AD = 4ms x counter2.
Mình edit lại đây :D

Source code:

#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );

const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};

//===== hàm khoi tao
void interrupt MyInt(void){
static int counter1,counter2;
// counter1 dem so lan Timer0 tran
// counter2 dem so lan ca 4 led duoc quet
static unsigned int number;
static unsigned int a[4]={0,0,0,0};
static unsigned char j; // biến đếm kiểm tra xem led nào đang được quét
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
if( ++counter1 == 10){
counter1 = 0;
PORTD = 0xFF;
PORTA = 0xFF - (1<< (j+1)) ;
PORTD = Font[a[j]];
if(j++ == 3 ) {
j=0;
RD0 = 0;
++counter2;
};
};
if(counter2 == 30 ){ // cap nhat so vao sau 300 ms
counter2 = 0;
if (ADIF == 0) {
ADGO = 1 ; // chuyen doi ADC tiep
a[3] = (unsigned char)number/1000;
a[2] = (number/100)%10;
a[1] = (number/10)%10;
a[0] = number%10;
};
};
};
if ( ADIE & ADIF){
//number = (unsigned int)((((ADRESH <<8) + ADRESL)*500)>>10);
//number = (unsigned int)((ADRESH * 256 + ADRESL ) * 500)>>10;
number=(ADRESH<<8)|ADRESL;
number=(unsigned int) (number* 4.8876); //5000/1023
ADIF = 0 ;
};
}

//Hàm khoi tao
void init(void)
{
//Khoi tao cho cac port
OPTION = 0b00000000;
TRISA = 0b00000001; // RA0 là input cho dau vao cua analog
TRISB = 0b11111111;
TRISC = 0b11111111;
TRISD = 0b00000000;
PORTD = Font[0];
TRISE = 0b11111111;

//Khoi tao cho ADC, co the viet don gian theo thanh ghi cung ok, viet nhu sau cho chinh sua don gian

ADFM = 1; // chon can le ben phai voi ket qua 10 bit
PCFG3 = PCFG2 = PCFG1 = 1; PCFG0 = 0;
// chon 1 dau RA0 la Analog con l?i la Digital, chon ap tham chieu la VDD - VSS
ADCS2 = ADCS1 = ADCS0 = 0 ; // chon tan so chuyen doi AD
CHS2 = CHS1 = CHS0 = 0 ; // chon chanle AN0 lam chuyen doi ADC
ADGO = 0 ;
ADON = 1; // Bat AD module

// Khoi tao cho ngat
GIE = 1; // Global Interrupt Enable
T0IE = 1; // Ngat timer0
TMR0 = 6;
PEIE = 1; // enable PI
ADIE = 1 ; // Ngat AD Module
}

//------------------------------------MAIN
void main(){
init();
ADGO = 1 ; // Bat dau chuyen doi ADC
while(1);
}

//=============== Hết


Chết thật viết bài mà vẫn còn quên. Các bạn chú ý: khi khởi tạo ADC chúng ta có thể viết ngắn hơn theo byte ADCON0, ADCON1. Nhưng ở đây tôi tách ra thành từng bit để cho chi tiết dễ chỉnh sửa hơn.

Chúc mọi người thành công. Mai viết tiếp :D

ngohaibac
05-01-2007, 03:58 PM
http://dientuvietnam.net/forums/showthread.php?t=1406&page=4
Bài viết số 39.

Theo datasheet PIC687XA tại trang 67,68 về PWM, chúng ta dễ dàng có thể viết được chương trình điều chế độ rộng xung (Pulse Width Modulation).

Chương trình dưới đây điều chế một xung với tần số 15KHz và có độ rộng xung tăng dần từ 0-> 100% theo bước tăng là 10% sau mỗi khoảng thời gian 1s.

PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
=> CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
với k là độ rộng xung (%) k = 0 -> 100

Sau đây là chương trình có kèm theo mô tả phần cứng:

/*;================================================ ========
; Ten chuong trinh : Dieu che do rong xung
; Nguoi thuc hien : Ngo Hai Bac (NOHB)
; Ngay thuc hien : 12/04/06
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; Dieu che do rong xung ra chan RC2/CCP1, chan RC2 noi voi led roi noi voi tro 220 Ohm, roi noi voi dat.
; => sau 1s thi tang do rong xung len 10%
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich : Phan chuong trinh nho cho du an lon :D
PWM dung timer2
;================================================= =======*/
#include<pic.h>
__CONFIG(HS & UNPROTECT & PWRTEN & BOREN & LVPDIS & WDTDIS );

//============ cac marco


//============= ham khoi tao
void init(void){
//===== init for PWM
// PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PR2 = 82; // Tan so = 15 KHz, TMR2 Prescaler Value = 4
// PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
// => CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
CCPR1L = 0;
TRISC2 = 0; // RC2 la output
RC2 = 1;
T2CON = 0b00000101; // Timer2 on, TMR2 Prescaler Value = 4
CCP1CON = 0b00001100; // CCP1 hoat dong trong che do PWM
//===== init cho SFR
OPTION = 0x00; // dung tro keo len PortB, TMR0 Prescaler = 2 va dung cho TMR0
TMR0 = 0x06; // khoi tao cho Timer0
T0IF = 0; // xoa co ngat timer0
T0IE = 1; // timer0 Interrupt Enable
GIE = 1; // Global Interrupt Enable
}

//============= ham ngat
void interrupt MyInt(void){
static volatile unsigned char k; // % do rong xung => 0<= k <= 100
static volatile unsigned int counter1;
int temp;
// ==== Ngat timer0
if (T0IE & T0IF ){
T0IF = 0;
TMR0 = 6;
if(++counter1 == 1000){
counter1 = 0;
temp = 4* (PR2 + 1) * k/100;
CCPR1L = temp>>2;
CCP1Y = temp - ((temp>>1)<<1);//temp%2;
CCP1X = (temp>>1)%2;
//CCPR1L = (TMR2 + 1)>>1 ;
k += 10; // tang 10%
if( k > 100) k=0;
};
};
}

//============= ham chinh Main
void main(void){
init();
while(1);
}


Chương trình đã được test bằng mạch thật. Hiện tượng: led sáng dần dần sau đó sáng rõ. Rồi lại tắt, tiếp tục sáng dần dần,..
Ngẫu hứng đêm khuya viết tí. Sáng mai dạy viết tiếp.

Chúc anh em ngủ ngon :D.

ngohaibac
05-01-2007, 04:04 PM
http://dientuvietnam.net/forums/showthread.php?t=1406&page=5
Bài số 45.

Giờ mình xin đưa ra các chương trình mà mình tối ưu dần dần và cảm thấy nó dễ hiểu. Mình xin đưa ra cho các bạn xem và cho ý kiến. Mình sẽ tối ưu từng chương trình một.

Đầu tiên là chương trình dùng giao tiếp USART, trong chương trình này mình dùng thư viện stdio.h có hàm printf(). Tuy nhiên bạn phải định nghĩa hàm putch(..) thì mới sử dụng được hàm này.

Hàm printf( ) sẽ truyền xâu dữ liệu theo định dạng C ra cổng nối tiếp USART.

/*================================================= =======
; Ten chuong trinh : giao tiep USART voi PC, nhan duoc thi hien thi lai
; Nguoi thuc hien : ngohaibac
; Ngay thuc hien :
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; chan RC7/TX noi voi chan R1OUT cua MAX232
; chan RC6/RX noi voi chan T1IN cua MAX232
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich : Chuong trinh dung giao tiep USART

;================================================= =======*/
#include<pic.h>
# include "stdio.h"

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

// ham init - khoi tao
void init(void){
// Khoi tao cho USART
TRISC = TRISC | 0b11000000; // Bit 7,6 la RX va TX phai la Input
SPEN = 1 ; // Enable Serial Port communication.
SYNC = 0; // che do khong dong bo Asynchronous
// cho che do truyen
TXEN = 1; //enable truyen
TX9 = 0 ; // chon che do 8 truyen bit du lieu
BRGH = 1; // High - speed
SPBRG = 129; //Baud = 9600; voi HS, Baud Rate = Fosc/(16(X+1))
TXIE = 0; // khong dung ngat Truyen
// Che do nhan du lieu
RCIE = 1; // dung ngat nhan
PEIE = 1; // cho phep ngat ngoai vi
GIE = 1; // cho phep ngat toan cuc
RX9 = 0; // nhan 8 bit
CREN = 1; // lien tuc nhan du lieu; = 0 k lien tuc nhan du lieu
}
// ham truyen du lieu
void putch(unsigned char byte)
{
/* output one byte */
while(!TXIF); /* set when register is empty */
// continue;
TXREG = byte;
}
// ham ngat
void interrupt MyInt(void){
unsigned char temp;
if(RCIF){ // Neu co ngat nhan du lieu noi tiep
temp = RCREG;
RCIF = 0; // Xoa co ngat RCIF
printf(" da nhan duoc du lieu: %c", temp);
};
}

// ham chinh
void main(void){
init();
while(1);
}


Chương trình này rất có ích khi muốn test chương trình giao tiếp qua USART.

Chúc các bạn thành công. Ngủ cái đã. Mai còn phải ôn thi :D.

ngohaibac
05-01-2007, 04:09 PM
http://dientuvietnam.net/forums/showthread.php?t=1406&page=5
bài 46.

Chào các bạn. Tôi đã làm xong bài tập lớn môn lý thuyết điều khiển tự động là thiết kế bộ điều khiển PID trên nền PIC.Bây giờ tôi xin đưa các đoạn code của bài tập lớn của tôi.

Đầu tiên là công việc là lấy đặc tính đáp ứng h(t) của động cơ để từ đó tính toán các tham số Kp, Ki, Kd. Đây là bước tính toán thô các giá trị của bộ PID sau đó mình mới tinh chỉnh lại sau ở một chương trình khác.

Vi điều khiển ứng dụng: PIC6F877A

Ngôn ngữ lập trình: HTPIC

Trong bài này tôi mục đích làm như sau: khi ấn "P" trên giao diện trên PC hay nói cách khác truyền kí tự P xuống chip thì nó nhận lệnh và cho động cơ hoạt động. Tôi điều chế một xung 15KHZ, ở đây cho độ rộng 100% luôn. Và từ đó liên tục đọc 500 giá trị và truyền lên PC.

Thời gian trích mẫu của hệ thống là 10ms. Tôi truyền số xung đo được lên PC, từ số liệu này sẽ tính toán ra tốc độ thực và vẽ được hàm h(t) của đối tượng. Tôi dùng chương trình Terminal (do lười nên không viết chương trình trên PC riêng) và lấy dữ liệu và cho vào Matlab để nội suy ra hàm quá độ h(t) . Tôi định viết một chương trình bằng Matlab nhận giao tiếp RS232 tính toán và đưa ra đồ thị luôn. Nhưng phải chờ tí đã, dạo này ôn thi nên hơi lười làm.

Chương trình Terminal và giao tiếp RS232 các bạn có thể xem tại
http://www.picvietnam.com/forum/showthread.php?t=274&page=2

Code chương trình trên Matlab: dùng nội suy Cubic
hold off;
x_rough= 0:0.01:5;
%x_fine= 0:0.05:0.8 ;% chon buoc noi suy tu xmin:0.1:xmax( voi xmin la gia tri nho nhat cua x_rough, xmax tuong tu;
x_fine = 0:0.001: 5;
data = [ ]; // Các giá trị số xung đo được 500 giá trị
data = data * 1000 /(10 * 100 *12);
% tính toán ra tốc độ thực và chia cho 12V để suy ra đáp ứng khi U = 1V vì coi động cơ DC là tuyến tính
% 100 là số lỗ /1 vòng của Encoder
inter_cubic= interp1(x_rough,data,x_fine,'cubic');
% noi suy theo phuong phap cubic
plot(x_fine,inter_cubic,'k','LineWidth',2);
grid on;


Code cho PIC6F877A

#include<pic.h>
# include "stdio.h"

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

const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};

# define Ts 10 // Thoi gian trich mau Ts (ms)
# define Encoder_resolution 100 // So lo cua Encoder/1 vong
# define Total_Point 500 // So diem can trich mau

// ham truyen du lieu
void putch(unsigned char byte)
{
/* output one byte */
while(!TXIF); /* set when register is empty */
// continue;
TXREG = byte;
}

//===== Ham khoi tao
void interrupt MyInt(void){
static volatile unsigned int i, Pulse_Encoder;
// i la so diem trich mau
// Pulse_Encoder = so xung do duoc tu Encoder
static volatile unsigned char allow,counter_Sampling;
// allow la bien cho phep bat dau trich mau
// counter_Sampling: bien dem de trich mau
unsigned char RC_USART; // gia tri doc duoc tu thanh ghi nhan du lieu USART
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
if((++counter_Sampling == Ts) && allow){ // Ts = 10 ms
Pulse_Encoder = (TMR1H << 8) | TMR1L;
// Toc do dong co = Pulse_Encoder * 1000 / (Encoder_resolution * Ts) (vong/s)
printf("%6d",Pulse_Encoder); // Truyen gia tri xung do tren Ts
counter_Sampling = 0;
if (i++ == Total_Point){
i = 0; // Neu trich duoc 500 diem thi dung dong co lai
CCPR1L = 0;
allow = 0;
};
};
};
if(RCIF){ // Neu co ngat nhan du lieu noi tiep
RC_USART = RCREG;
RCIF = 0; // Xoa co ngat RCIF
switch(RC_USART){
case 'P': // === Bat dau cho dong co chay cho do rong xung = 100%
TMR1ON = 0 ; // ngung Timer1
TMR1H = TMR1L = 0;
TMR1ON = 1 ; // bat lai Timer1
CCPR1L = PR2 + 1;
CCP1Y = CCP1X = 0;
allow = 1;
break;
};
};
}

//------------------------------------init
void init(void){
// Khoi tao cho USART
TRISC = TRISC | 0b11000000; // Bit 7,6 la RX va TX phai la Input
SPEN = 1 ; // Enable Serial Port communication.
SYNC = 0; // che do khong dong bo Asynchronous
// cho che do truyen
TXEN = 1; //enable truyen
TX9 = 0 ; // chon che do 8 truyen bit du lieu
BRGH = 1; // High - speed
SPBRG = 129; //Baud = 9600; voi HS, Baud Rate = Fosc/(16(X+1))
TXIE = 0; // khong dung ngat Truyen
// Che do nhan du lieu
RCIE = 1; // dung ngat nhan
PEIE = 1; // cho phep ngat ngoai vi
GIE = 1; // cho phep ngat toan cuc
RX9 = 0; // nhan 8 bit
CREN = 1; // lien tuc nhan du lieu; = 0 k lien tuc nhan du lieu

//===== init for PWM
// PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PR2 = 82; // Tan so = 15 KHz, TMR2 Prescaler Value = 4
// PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
// => CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
CCPR1L = 0;
TRISC2 = 0; // RC2 la output
RC2 = 1;
T2CON = 0b00000101; // Timer2 on, TMR2 Prescaler Value = 4
CCP1CON = 0b00001100; // CCP1 hoat dong trong che do PWM

//================= init for PORTs
OPTION = 0b00000000;
ADCON1 = 0b00000111;
TRISA = 0b00000000;
TRISD = 0b00000000;
PORTD = 0xFF;

//================ Khoi tao cho Timer0
GIE = 1;
T0IE = 1;
TMR0 = 6;

// ========= Khoi tao cho dem Timer1
TMR1CS = 1; // Timer1 hoat dong o che do Counter Mode
T1SYNC = 1; // TMR1 hoat dong o che do dem khong dong bo
T1OSCEN = 1; // Dem xung tu chan RC1/T1OSI/CCP2
T1CKPS1 = T1CKPS0 = 0; // Chon Prescaler = 1:1
TMR1H = TMR1L = 0;
TMR1IE = 0 ; // Khong dung ngat Timer1
TMR1ON = 1; // Bat Timer1
}

//------------------------------------MAIN
void main(){
init();
while(1);
}

// === Kết thúc


Chương trình đã test và cho đặc tính h(t) thí dụ với động cơ 12V của tôi như sau:

Hình bị mất, mình tìm lại upload sau:D.

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

ngohaibac
06-01-2007, 09:44 AM
Chào các bác.Em mới học về Pic.Mong các bác chỉ giáo
Em dùng Htpic.
Em viết 1 chương trình đơn giản sử dụng timer0.
Nhưng chả hiểu tại sao thời gian delay ko chính xác(em mô phỏng bằng proteus).
Em delay 1 giây mà mô phỏng chạy những 15 giây(sai số lớn quá)
Mà ko hiểu tại sao lệnh while(1) lại ko lặp lại.Khi đèn chạy được 1 chu kỳ thì nó tắt luôn chứ ko lặp lại.
các bác xem giúp em với


//================================================== ======
//Bai toan phanh xe.Phanh duoc noi vao RB0
//khi phanh thi RB0 o muc thap
//binh thuong RB0 o muc cao
//co 8 led o RD8 den RD0 se sang theo quy luat(khi phanh)
//10000000,01000000...00000001,11111111,00000000
//sau do lap lai neu chua nha phanh
//thoi gian delay la 1 giay
//thach anh 20 Mhz

//================================================== ======
#include<pic.h>
#define out PORTD
__CONFIG(HS & PWRTEN & BOREN & LVPDIS &WDTDIS );
void DL(unsigned int giay);
//--------------------------------------------------------------------------------------------------
const unsigned char a[]={0b10000000,0b01000000,0b00100000,0b00010000,0b00 001000,0b00000100,0b00000010,0b00000001,0b11111111 ,0b00000000};
//================================================== ======
void main()
{
unsigned char i;
TRISB = 0b11111111; //Dinh nghia cong B la INPUT
RBPU =0; //co dien tro trong keo len nguon
TRISD = 0b00000000;
i=0;
while(1)
{
if(RB0==0) //nhan phanh
{
out=a[i];
i=i+1;
DL(25000); //delay 1giay
if(i==11) i=0;
}
else
{
out=0;
i=0;
}
}
}

//------------------------------------------------------------------------
void DL(unsigned int giay)
{
while(giay--)
{
//delay 40 microgiay
PSA=1; //bo chia dung cho wdt
T0CS=0; //dung dem thoi gian
TMR0=56;
while(!TMR0IF);
TMR0IF=0;
}
}
//=============================THE END===========================


Bạn xem lại code xem. Trong HTPIC định nghĩa thanh ghi TMR0IF là T0IF chứ nhỉ? Nó không định nghĩa TMR0IF đâu. Bạn xem lại đi rùi sửa nếu sai thì xin ý kiến tiếp :D.

Tiếp, mô phỏng bằng Poteus, quét led hiển thị không chính xác bạn ạ. Nên thử bằng Board thật nhé, xem có vấn đề gì không.

Trong hàm delay của bạn, là kiểu

ngohaibac
14-03-2007, 01:29 AM
Chào các bạn.

Để có thể viết được chương trình bằng HTPIC cho hợp lý và tuân theo đúng trình dịch HTPIC, các bạn nên download manual của nó
PICC Manual (http://fs05n4.sendspace.com/dl/e97d5cbd87b0bd900cc5a4de9fdf67ed/45f6ecaa/ieihnt/picc-manual.zip)

Tài liệu này rất hay (của www.htsoft.com).

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

ngohaibac
06-04-2007, 02:36 PM
Chào các bạn.

Mình thấy quyển manual complier của bọn HTsoft cũng khá hay và đầy đủ chú ý. Do đó, thấy cái gì hay hay mình viết rùi các bạn góp ý kiến nhá. Có lẽ mình cũng nên lập thư viện cho HTPIC chứ nhỉ?? Thấy anh em dùng CCS hoạt động kinh quá :D.

Đầu tiên là cách khai báo một biến đặt tại một địa chỉ nhất định trong RAM.

Ví dụ, muốn Portvar là biến đặt tại địa chỉ 0x06 thì trong ASM ta dùng lệnh sau:

_Portvar EQU 06h

Khi đó mỗi khi thao tác với biến Portvar tức là thao tác với ô nhớ 06h.

Trong HTPIC các bạn khai báo như sau:

volatile unsigned char Portvar @ 0x06;


Chú ý từ khóa @.

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

ngohaibac
06-04-2007, 02:36 PM
Mình xin upload thư viện viết cho LCD, ở đây mình dùng 8 bit mode cho LCD 2 line x 16 colum.


// LCD.h
#ifndef LCD_H
#define LCD_H

# include <pic.h>

//============== Using LCD - 2 line, 16 colum
#define LCD_MODE_2x16 (TRUE) // HDM16216H-2, HDM16216H-4, HDM16216H-5, HDM16216H-B, HDM16216H-D, HDM16216L-2, HDM16216L-5, HDM16216L-7, HDM16216L-D, HDM16216L-B, HDM16216H-I

#define LCD_CURSOR_BLINK (FALSE) // Blink/Noblink cursor mode
#define LCD_CURSOR_ON (TRUE) // Cursor visible
#define LCD_CURSOR_INCREMENT (TRUE) // Set left-to-right cursor movement
#define LCD_CURSOR_SHIFT (FALSE) // Shift display on entry

#define LCD_DISPLAY_ON (TRUE) // Turn display on/off

#define LCD_ALLOW_USER_CHARS (TRUE) // Controls whether display uses ASCII for control chars or uses user-defined chars in lcd_putc()
#define LCD_ENABLE_GETC (TRUE) // Save code space by setting to FALSE
#define LCD_ENABLE_GOTOXY (TRUE) // any functions which you will not
#define LCD_ENABLE_PRINTF (TRUE) // need in your application.
#define LCD_ENABLE_UNSCROLL (TRUE)
#define LCD_ENABLE_SCROLL (TRUE)
#define LCD_ENABLE_CLEAR (TRUE)

#define LCD_MAXROWS ((unsigned char)(2))
#define LCD_MAXCOLS ((unsigned char)(16))
# define LCD_MULTI_LINE (TRUE)

#define LCD_8_BIT_MODE (TRUE)

//======================= Define LCD_PORT
#define LCD_DATA_PORT PORTD // Port on which LCD data lines are connected
#define LCD_TRIS_PORT TRISD // Need to specify the corresponding TRIS

# define LCD_RS RA1
# define LCD_RW RA2
# define LCD_E RA3

# define LCD_TRIS_E TRISA1
# define LCD_TRIS_RW TRISA3
# define LCD_TRIS_RS TRISA2

// ======================= Define command code
#define LCD_COMMAND_CLEAR ((unsigned char)(0x01)) //1.53 ms // Clear screen, home cursor, unshift display
#define LCD_COMMAND_HOME ((unsigned char)(0x02)) //1.53 ms // Home cursor, unshift display
#define LCD_COMMAND_BACKSPACE ((unsigned char)(0x10)) // Move cursor left one (destructive based on LCD_DESTRUCTIVE_BS)
#define LCD_COMMAND_FWDSPACE ((unsigned char)(0x14)) // Move cursor right one
#define LCD_COMMAND_PANLEFT ((unsigned char)(0x18)) // Move screen left one
#define LCD_COMMAND_PANRIGHT ((unsigned char)(0x1C)) // Move screen right one


// ==================== Declare some functions
void delay_us (unsigned char us);
void delay_ms(unsigned char ms);
unsigned char LCD_getByte (void);
void LCD_PrByte (unsigned char c);
void LCD_Command(unsigned char c);
void LCD_PrChar (unsigned char c);
void LCD_gotoXY(unsigned char row, unsigned char col);
unsigned char LCD_getChar (void); // Read character at cursor
void LCD_Init(void);
void LCD_PrString (const char* message);

#endif

Các bạn sẽ thấy là khi muốn dùng LCD thì đầu tiên các bạn khai báo thông số cho LCD như các chân RS, RW, E, LCD_PORT ở Define LCD_PORT. Mặc định mình khai báo là: LCD_PORT là PortD, RS là RA1, RW là RA2, E là RA3.

Các bước thực hiện:

- Khởi tạo LCD dùng lệnh: LCD_Init();
- Thao tác ghi đọc bình thường, chú ý nhất là các hàm: LCD_gotoXY, LCD_PrString, LCD_PrChar, LCD_Command.

Tiếp theo là file LCD.c là file thực hiện:


//LCD.c
# include "lcd.h"

// ==== Some constants for LCD 16x2
const unsigned char const LCD_ROW_ADDRESS[] = // Row/Column information for LCD_gotoxy()
{
0x00, // Line 1
0x40 // Line 2
};

const unsigned char const LCD_INIT_STRING [] = // LCD Init String on powerup
{
0b00000001, // Clear display
0b00000010, // Home cursor
};

//================================================== ========================================
void delay_us (unsigned char us){
while(us--){
asm("nop");
asm("nop");
};
}

//================================================== ========================================
void delay_ms(unsigned char ms){
unsigned char i, j;
while(ms--){
for (i = 0; i < 20; i++)
for (j = 0; j < 100; j++)
asm("nop");
};
}
// ================================================== ==========================================
unsigned char LCD_getByte (void){
unsigned char retval; // Return value
LCD_TRIS_PORT = 0xFF; // Set port to all input
LCD_RW = 1; // Tell LCD we want to read
delay_us(2);
LCD_E = 1; // Do the read
delay_us(2);
retval = LCD_DATA_PORT;
LCD_E = 0;
LCD_TRIS_PORT = 0x00; // Set port back to outputs
return (retval);
}
//================================================== ==================================================
void LCD_PrByte (unsigned char c){ // Write byte to port in current RS mode
unsigned char RS_Status;
RS_Status = LCD_RS; // Get old pin state
LCD_RS = 0; // Force into command mode to read state
while (LCD_getByte () & 0x80); // Wait for read state
if (RS_Status)
LCD_RS = 1; // Restore RS to old state
delay_us (1);
LCD_RW = 0; // Set to write mode
delay_us (1);
LCD_DATA_PORT = c; // Send the character out
LCD_E = 1;
delay_us(1);
LCD_E = 0;
}
//================================================== ==============================================
/*Ham yeu cau goi lenh dieu khien LCD*/
void LCD_Command(unsigned char c){ // Send command to LCD port
LCD_RS = 0;
LCD_PrByte(c);
}
//================================================== ==============================================
/*Ham yeu cau goi du lieu hien thi len LCD*/
void LCD_PrChar (unsigned char c){ // Write character to LCD
LCD_RS = 1 ;
LCD_PrByte(c);
}
//================================================== ===============================================
void LCD_gotoXY(unsigned char row, unsigned char col){
if (row > LCD_MAXROWS) // Range limit
row = LCD_MAXROWS;
if (col > LCD_MAXCOLS)
col = LCD_MAXCOLS;

row = LCD_ROW_ADDRESS[row-1]; // Get address of first byte on desired row
row += col - 1;
LCD_Command (0x80 | row); // Write new cursor address
}
// ================================================== ===================================
unsigned char LCD_getChar (void) // Read character at cursor
{
unsigned char retval; // Return value
LCD_RS = 1;
retval = LCD_getByte ();
LCD_RS = 0;
return (retval);
}

//================================================== =====================================
void LCD_Init(void){
unsigned char i;

LCD_TRIS_PORT = 0x00;
LCD_TRIS_E = 0;
LCD_TRIS_RW = 0;
LCD_TRIS_RS = 0;

LCD_E = 0 ;
LCD_RS = 0;
LCD_RW = 0;

//delay_ms(100); // Tao tre 100ms cho LCD khoi dong

LCD_PrByte (0b00111000); //Function set ; DL = 1(8 bits) , N = 1 (2 lines), F = 0 (5x8 dots)
LCD_PrByte (0b00001100); // Display on/off control
LCD_PrByte (0b00000110); // Entry mode set

LCD_PrByte(LCD_COMMAND_CLEAR);
LCD_PrByte(LCD_COMMAND_HOME);
}

// ================================================== =================================================

void LCD_PrString (const char* message){ // Write message to LCD (C string type)

while (*message) // Look for end of string
LCD_PrChar (*message++); // Show and bump
}


Các bạn thêm 2 file này vào trong Project của mình và nhớ include file LCD.h vào chỗ đầu file chứa hàm Main nhé.

Các bạn có thể mô phỏng bằng Proteus chạy rất ok. Lúc nào gửi tiếp mấy cái đã test.

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

tranvanthuong
06-04-2007, 03:38 PM
chào các anh! em mới học pic hà! khi em cài MPlab 7.52 roi ccs c, thêm pluginmp6 nữa nhưng khi khởi động chương trình Mplab lên thì báo lổi
Project Manager's initialization failed: At least the MPASM toolsuite plugin or AMS30 toosuite plugin must be installeed.(MPLAB may be to be reintalled)
em không biết lổi trên và cách khắc phục như thế nào nhờ các anh chỉ bảo,
em muốn viết 1 chương trình cho pic bằng c ma cả tháng rồi mò cài chương trình chưa được MPLAB em có 3 bản 7.20,7.50,7.52 còn ccs c thi chưa có anh nào có ccsc ma xài được cho em với, các link bên picvietnam chết hết rồi .
thân chào!!!

tranvanthuong
06-04-2007, 03:39 PM
em muốn xài HTPIC anh hướng dẫn em nghe anh ngohaibac

em hy vọng anh ngohaibac sẽ làm cho HTPIC mình rôm rả lên so với mấy anh bên ccs c bây giờ em mới bắt đầu nhưng hy vọng 2 tháng sau em viết được chương trình bự bự pots lên khoe với anh em (quang báo chẳng hạn!hi hi) hit hit nhưng bay giờ ko biết máy em có lổi ko mà MPLAB hết chạy được rùi

http://www.picvietnam.com/forum//forumdisplay.php?f=34

@ngohaibac: Lần sau không được spam nhé em.

ngohaibac
07-04-2007, 12:31 AM
Project Manager's initialization failed: At least the MPASM toolsuite plugin or AMS30 toosuite plugin must be installeed.(MPLAB may be to be reintalled)

Lỗi này là do khi em cài MPLAB không đủ đó, nó thiếu MPASM toolsuite và ASM30 (asm cho PIC30F) nên nó không khởi động dc. Có lẽ là do em cài kiểu gì đó nên k cài cái MPASM toolsuite là complier ASM.

Em cài lại chú ý chọn Custom Option khi nó cho lựa chọn khi cài nhé, rùi chọn hết mà cài cho chắc chắn. Cái này giống cài nhiều phần mềm mà em.

Chúc em thành công.

tranvanthuong
07-04-2007, 04:32 PM
em cai custom roi nhung cung ko duoc anh a!
ko hiểu nỗi hôm trước em cài và dùng được nhưng từ khi gở ra cài lại thì ko thảnh công không biết tại sao nữa

@ngohaibac: Lần sau em viết bài thì phải viết dài, hỏi thì hỏi vào một bài là được. Em vào luồng về MPASM để thảo luận và xem các anh chị đã làm nhé.
http://www.picvietnam.com/forum//forumdisplay.php?f=34

Chúc em thành công.

ngohaibac
09-04-2007, 01:41 AM
Tiếp theo là về module I2C, một chuẩn giao tiếp quan trọng khi giao tiếp với ngoại vi như EEPROM, RTS(DS1307),...

Do đó, mình xin cung cấp cho các bạn các hàm và thực thi của các hàm này trên HTPIC. Mình có tham khảo cả ở bọn htsoft nhưng nó viết sai một số hàm không chạy được, mình đã viết lại toàn bộ.

Đầu tiên là hàm I2C.h:

//I2C.h
//Declare some functions
void I2C_Init(void); // khởi tạo I2C ở chế độ Master, Baud = 100 Khz
void I2C_waitForIdle(void); // Chờ khi nào đường bus ở chế độ Idle (rảnh rỗi)
void I2C_Start(void); // Khởi động I2C - Master chiếm đường bus
void I2C_repStart(void); // Chế độ Restart
void I2C_stop(void); // Stop I2C - Master nhường đường bus cho thiết bị khác
unsigned char I2C_write( unsigned char I2CWriteData ); // ghi một byte lên đường SDA
unsigned char I2C_read( unsigned char ack ); // Đọc một byte với mã ACK (ACK = 0 nếu ack = 1, và ACK = 1 nếu ack = 0) -> dùng xác nhận từ master đối với slave.
void I2C_NACK(void); // tạo bít Not Ack


Và sau đây là thực thi của các hàm này:

// I2C.c
# include "pic.h"
# include "I2C.h"
//================================================== ================================================== ==
void I2C_Init(void){
/* // Configure for Master Mode
SSPM3 = 1;
SSPM2 = 0;
SSPM1 = 0;
SSPM0 = 0; ss // I2C Master Mode, clock = Fosc/(4*(SSPADD + 1));

WCOL = 0; //No conllision

SSPEN = 1; // Enables the serial port and
*/
SSPCON = 0b00101000; // set IIC port to Master mode with BRG
SSPSTAT = 0b00000000; // Standard speed mode - 100Hz
SSPCON2 = 0;

//TRIS_SCL = 0;
//TRIS_SDA = 0; // configure SDA and SCL as Output

SSPADD = 9; // BAUD = 100KHz
SSPIF = 0; // clear SSPIF interrupt flag
BCLIF = 0; // clear bus collision flag
STAT_CKE = 0; // use I2C levels worked also with '0'
STAT_SMP = 1; // disable slew rate control worked also with '0'
}
//================================================== ===========================
void I2C_waitForIdle(void)
{
while (( SSPCON2 & 0x1F ) | STAT_RW) ; //CLRWDT(); // wait for idle and not writing
}

//================================================== ===========================
void I2C_Start(void){
//SSPIF = 0;
SEN = 1;
//while(!SSPIF);
while(SEN);
}
//================================================== ============================
void I2C_repStart(void)
{
I2C_waitForIdle();
RSEN = 1;
}
//================================================== ===========================
void I2C_stop(void)
{
I2C_waitForIdle();
PEN = 1;
}
//================================================== ============================
unsigned char I2C_write( unsigned char I2CWriteData ){
I2C_waitForIdle();
SSPBUF = I2CWriteData;
I2C_waitForIdle();
return (!ACKSTAT); // function returns '1' if transmission is acknowledged
// 1: Success
// 0: Fail to send
}
//================================================== ==========================
unsigned char I2C_read( unsigned char ack ){
unsigned char I2C_ReadData;
I2C_waitForIdle();
RCEN = 1;
I2C_waitForIdle();
I2C_ReadData = SSPBUF;
I2C_waitForIdle();
if ( ack ) ACKDT=0;
else ACKDT = 1;
ACKEN = 1; // send acknowledge sequence
I2C_waitForIdle();
return( I2C_ReadData );
}
/************************************************** ****************************************/

void I2C_NACK(void)
{
I2C_waitForIdle();
if (ACKSTAT){
PEN=1; //Stop
I2C_waitForIdle(); //Wait until action is finished
while(PEN);
};
}

Còn việc dùng nó quá đơn giản, ví dụ với Ds1307 thì đầu tiên bạn phải:

- Khởi tạo I2C bằng I2C_Start();
- Start bằng I2C_Start();
- Chọn slave giao tiếp bằng cách ghi địa chỉ và bit RW tương ứng với chế độ đọc hay ghi.
- Ghi dữ liệu lựa chọn byte nào cần ghi hay cần đọc trong bảng RAM của DS1307.
- Ghi dữ liệu hay là đọc dữ liệu.

Chú ý: khi ghi xong, muốn đọc thì phải làm lại tức là phải restart nhé.

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

tranvanthuong
09-04-2007, 09:39 AM
cám ơn anh ngohaibac để em cài cái máy tính của em rồi em làm lại những gì anh hướng dẫn thữ xem sao! em sẽ không bao giờ bỏ cuộc cả hôm nay em sẽ cài máy lại rồi cài MPLAP rồi cài HT-pic và CCS C luôn

@nohb: những cái này em có thể chát Yahoo với anh. Anh đề nghị không spam bài ở đây. Để cài HTPIC, CCS em xem hướng dẫn là cài được.

Em xem xong anh sẽ del bài này đó.

ngohaibac
27-07-2007, 04:50 PM
Chào các bạn.

Mình thấy các thư viện của mình vẫn chưa tối ưu. Thư viện sẽ phải có thêm các lựa chọn là các constant để thiết lập cho các hàm Init.

Các trình dịch tự sinh mã đều có các yếu tố này nhưng mà thấy C18, C30 có cách đặt tên các lựa chọn này khá hay.

Nên bạn nào có thời gian thì nên viết lại và thêm các constant này vào thì chương trình sẽ có tính sử dụng lại cao. Mình có thời gian sẽ viết lại thêm.

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

toanck86
28-11-2007, 12:04 AM
các bác cho em hỏi HTPIC với HTPIC 18 có khác nhau không vậy :D

quangdk
24-01-2008, 10:30 AM
Em cam on Bac nhieu lam.Bac that rong luong.thanh vien moi

minhham
28-04-2008, 10:22 PM
chào các bác, em đang làm bài tập điều khiển động cơ bước loại 4 pha,2cuộn dây, 1 nguồn 5V chung cho 2 cuộn dây. Góc bước 7.5 độ. Làm và mô phỏng trên mạch thật mà mãi ko được. phát nản cả người. với đoạn code dưới thì động cơ quay bốn bước thì dừng, ko quay nữa, bấm nút thì động cơ lại quay tiếp.
Hình trên proteous mang tính chất minh họa, vì ko mô phỏng trên proteous
thuật toán là cứ sau mỗi lần cấp xung tới các cuộn dây của động cơ thì lại check nút bấm và cấp xung tiếp theo đúng chiều để động cơ quay cho phù hợp với yêu cầu nút bấm.
nếu bác nào có code về bài tập này thì up lên cho anh em xem với!
code:
// DIEU KHIEN DONG CO BUOC: loai 4 pha, goc buoc 7.5do, dien ap 5V
// Nut bam RB0 : Quay trai; nut RB1 : dung; RB2 : Quay phai
// yeu cau: dong co dang quay trai neu bam nut quay phai (mot lan, ko can bam nhieu lan) thi doi chieu va quay phai.
// dong co dang quay phai neu bam nut quay trai (mot lan) thi doi chieu va quay trai
// dong co dang quay bam nut dung thi dung lai, nhung PORTD van duoc xuat ra 1 gia tri bang gia tri cuoi cung ngay truoc khi dung

#include<pic.h>
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS);
// ============= KHAI BAO CAC CHUONG TRINH CON ===========
// ============= CHU Y: phai xap xep theo dung thu tu chuong trinh con o duoi. Mot loi ngo ngan HAHAHA =========
char phimbam(void);
void DL(unsigned int i);

// ============= CHUONG TRINH CHINH ===========
void main ()
{ // ============= KHOI TAO ============
static char a; // bien a dieu khien trang thai hoat dong cua cua dong co
OPTION = 0b00000000; // dung prescaler cho timer0 voi ti le 1:2 Va dung tro keo len PORTB
TRISB = 0b00000111; // chan RB0, RB1, RB2 la input
TRISD = 0b00000000; // PORTD la cong ra
PORTD = 0b01010000; // PORTD gia su dang o vi tri dau ung voi gia tri 0b01010000, cac vi tri vai tro nhu nhau.
while (1)
{ a = phimbam();
if (PORTD == 0b01010000)
{ switch(a)
{ case 1 : { DL (5000); //trai
PORTD = 0b10010000; };
break;
case 2 : { DL (5000);
PORTD = 0b01010000; };
break;
case 3 : { DL (5000);
PORTD = 0b01100000; }; //phai
break;
};
};

if (PORTD == 0b10010000)
{ switch(a)
{ case 1 : { DL (5000); //trai
PORTD = 0b10100000; };
break;
case 2 : { DL (5000);
PORTD = 0b10010000; };
break;
case 3 : { DL (5000);
PORTD = 0b01010000; }; //phai
break;
};
};

if (PORTD == 0b10100000)
{ switch(a)
{ case 1 : { DL (5000); //trai
PORTD = 0b01100000; };
break;
case 2 : { DL (5000);
PORTD = 0b10100000; };
break;
case 3 : { DL (5000);
PORTD = 0b10010000; }; //phai
break;
};
};

if (PORTD == 0b01100000)
{ switch(a)
{ case 1 : { DL (5000); //trai
PORTD = 0b01010000; };
break;
case 2 : { DL (5000);
PORTD = 0b01100000; };
break;
case 3 : { DL (5000);
PORTD = 0b10100000; }; //phai
break;
};
};
}
}


// =========== CAC CHUONG TRINH CON ============
//==============================================
// chuong trinh "phimbam" phai lam sao de an 1 lan la duoc? chu ko can an nhieu lan hoac la phai giu nut an 1 luc ???????

static char phimbam(void)
{ if ((RB0==0)&&(RB1==1)&&(RB2==1)) return (1); // dong co quay trai

if ((RB1==0)&&(RB0==1)&&(RB2==1)) return (2); // dong co dung

if ((RB2==0)&&(RB1==1)&&(RB0==1)) return (3); // dong co quay phai
}
//================ HAM DELAY DUNG TIMER0 =============
void DL(unsigned int i)
{ while (i--)
{
TMR0 = 6;
T0IF = 0;
while (!T0IF);
};
}

-> động cơ quay bốn bước dừng chắc do biến ''a'' ko giữ được giá trị ở vòng while tiếp theo.

tran_binh
28-11-2009, 01:41 PM
hiên nay minh đang làm đồ án đồng hồ số hiện thị trên led 7 đoạn (dùng led đơn kết nối như led 7 đoạn). với kích thước 43*130 cm. nhưng phần cứng thì minh đã làm nhưng chưa chạy được vì port quét led chưa hoạt động còn port quét dữ liệu data thì hoạt động. mong các anh em tư vấn giùm minh. minh sử dụng ic 89c51 lập trình và chương trình đã thành công nhưng phần cứng thì chưa {minh xuất dữ liệu ra mưc 0} http://www.megaupload.com/?d=KH8OLX77
nho tu van goi qua mail: tranthanhbinh8888@gmail.com

Locangel
15-12-2009, 12:45 AM
Bac ơi cho mình hỏi bạn viết bằng chuong trình biên dịch nào thế CCS-C hay là HTPICC

nhulinh
15-12-2009, 07:39 AM
Anh Bắc ơi, có bài nghiên cứu nào của anh về điều khiển LED ma trận post cho mọi người tham khảo với...
Thanks

ALU
27-01-2010, 10:57 AM
Lỗi này là do khi em cài MPLAB không đủ đó, nó thiếu MPASM toolsuite và ASM30 (asm cho PIC30F) nên nó không khởi động dc. Có lẽ là do em cài kiểu gì đó nên k cài cái MPASM toolsuite là complier ASM.

Em cài lại chú ý chọn Custom Option khi nó cho lựa chọn khi cài nhé, rùi chọn hết mà cài cho chắc chắn. Cái này giống cài nhiều phần mềm mà em.

Chúc em thành công.

Theo tôi đây là lỗi khá nhiều người gặp nhưng vẫn chưa có một trả lời nào xác đáng! Ngay cả trên forum của microchip cũng chưa trả lời rõ ràng.

Tôi cũng gặp tình cảnh tương tự!
Win của tôi là XP SP2 có bản quyền, phần mềm chống virus cũng là BKAV bản quyền.

Cài xong thì không thể khởi động nên không thể chỉ đường dẫn nhúng các trình biên dịch vào mplab IDE như hỉ dẫn trên microchip được.

Ai thực sự đã giải quyết triệt để lỗi trên thì chỉ dẫn cho anh em!
-------------------------------
Tôi đã xử lý được theo cách sau:
http://www.picvietnam.com/forum/showthread.php?t=5804

congtam1189
18-03-2010, 09:28 AM
sao khobg cho dơn de

congtam1189
18-03-2010, 09:34 AM
sao ko cho dơn ve

dienbk36
27-03-2010, 12:31 PM
Cám ơn anh Bắc!

eros_89_a
28-05-2010, 08:01 PM
anh Bắc cho em hỏi tí ở chỗ bài nháy led dùng pp delay .theo em thấy mỗi vòng lặp while (time--) chi co 250us phải kô anh ?anh giải thik dùm em với.em mới học pic .cám ơn anh!

QED
23-07-2010, 11:04 PM
Mình đang bí trong vấn đề quét led matrix. Bạn có thể giúp đỡ? có cả mạch kèm theo được không?
Rất cảm ơn!

haneishun
24-07-2010, 09:12 AM
em mới học Pic nên chưa hieu nhiều lắm có ai chỉ giứp em bài này được ko :hiển thị 1 số thực trên LCD.VD: hiển thị số 456,7

linhta07
17-11-2010, 11:17 AM
.......................thanks NOHB !

hoangcuibap
02-05-2011, 10:45 AM
Co bac nao dung dc ca hai phan mem ccs va htpic ko? Em moi vao nghe nen hai phan mem nay ko bt chon cai nao. Nho cac bac chi giao.

dovanhung
03-08-2011, 09:32 PM
huyentien8688@gmail.com
Cac buoc Crack HT PICC for pic 10/12/16

1. Cài đặt MPLAB IDE trong đó có kích chọn Hi-tech C compiler for PIC (hoặc chọn luôn complete).
2. Sau khi cài đặt HT-Pic sẽ vào một thư mục riêng trong Program files. Chạy file Activate or TRIAL PRO mode (Trong trường hợp của tôi là: "C:\Program Files\HI-TECH Software\PICC\9.81\resources\setup.exe"). Nó sẽ hỏi các bác dùng trial hay active luôn. Chọn "active PRO/Standard mode". Tick vào Off-line activation by email. Rồi điền một cái serial number bất kỳ sáu số. VD. 654321. Sau đó click finish
3. Chại cái chương trình "phát mã khóa" .exe rồi chỏ đến file HCPICP-654321-activation-request.txt trong thư mục cài đặt HT-pic. Cái thuốc này sẽ phát một file khóa giống như bác đã mua từ email (he he).
4. Chạy HT-PIC activation một lần nữa, nó sẽ chúc mừng các bác đã dùng bản PRO.

ductien88
19-09-2011, 05:50 PM
nên chọn CCS . vì hok cần nướng chín cũng thịt được luôn :D

tuanpham0101
19-03-2012, 01:00 AM
có vẻ ít người dùng HTPIC hay sao mà mình thấy threat này vắng vẻ quá.
sau đây mình post một vài code mình mới viết, cũng là newbye nên rất mong mọi người đóng góp ý kiến :d

tuanpham0101
19-03-2012, 02:21 AM
Em đang load thì mất điện, giờ mới load được :d

tuanpham0101
23-03-2012, 01:13 AM
đây là code đo độ rộng xung bằng ngắt RB0, từ đó tạo xung PWM bằng hàm delay hoặc CCP của Pic

tuan_utc
04-05-2012, 12:31 PM
Các bạn ơi ! cho mình hỏi bạn nào có tài liệu hướng dẫn học HT Pic cụ thể không? cho em xin với. Đang làm đề tài tốt nghiệp liên quan đến ngôn ngữ lập trình này.

thiepvespa
19-06-2012, 12:02 PM
đây là code đo độ rộng xung bằng ngắt RB0, từ đó tạo xung PWM bằng hàm delay hoặc CCP của Pic

Mình đang sử dụng PWM của Timer2, nhưng mình ko biết truy bắt thời điểm khi TMR2=CCPR1L như thế nào??? Ví dụ như trường hợp TMR2=PR2 thì TMR2IF được set nên có thể biết thời điểm này. Mong các bạn giúp đỡ

quitnownpc
21-06-2012, 01:54 AM
Em đang làm đồ án về Pic16f877a và ICds1307 hiển thị thời gian thực ngày tháng năm giwof phút giây. Em làm hoài mà ko làm đc anh nào biết chỉ dùm em với

anhnam231190
11-05-2013, 03:14 PM
em đang làm đồ án led matrix 16x128 dùng pic 16f877a giao tiếp máy tính, em làm được hienr thị chữ rồi nhưng chưa dịch được chữ,mong các anh chị pro giúp em với
http://www.mediafire.com/?a6t0aec48dar5p2
đây là mô phỏng và code của em.

pvthang123456
19-05-2013, 12:46 AM
các bác ơi. ai giup mình viết lại đoạn code này thành HTC được ko, chứ viết kiểu này mình ko hiểu, cho mình hỏi lun mấy cai thông số cài đặt timer0 là sao vậy
"#include<p18f4550.h>
#pragma config FOSC = HSPLL_HS // Using 20 MHz crystal with PLL
#pragma config PLLDIV = 5 // Divide by 5 to provide the 96 MHz PLL with 4 MHz input
#pragma config CPUDIV = OSC1_PLL2 // Divide 96 MHz PLL output by 2 to get 48 MHz system clock
#pragma config USBDIV = 2 // USB clock comes from 96 MHz PLL output / 2
#pragma config IESO = OFF // Disable Oscillator Switchover mode
#pragma config PWRT = OFF // Disable Power-up timer
#pragma config BOR = OFF // Disable Brown-out reset
#pragma config VREGEN = ON // Use internal USB 3.3V voltage regulator
#pragma config WDT = OFF // Disable Watchdog timer
#pragma config MCLRE = ON // Enable MCLR Enable
#pragma config LVP = OFF // Disable low voltage ICSP
#pragma config ICPRT = OFF // Disable dedicated programming LAT (44-pin devices)
#pragma config CP0 = OFF // Disable code protection

void timer0_2500();
void capnhat(),test_tay(),dungyen();
void ngatmuccao(void);
void timer0_10();
volatile unsigned char i=0,j=0,H=0xFF,L=0xE1;
volatile unsigned int pulse_max,pulse_top,set = 2000;

//--------------------------------------------------------------------
volatile unsigned int SERVO[16];

void delay_us( int x)
{
int i;
for(i=0;i<x;i++)
{}

}
void delay_ms( int x)
{
int i;
for(i=0;i<x;i++)
{
delay_us(1000);
}
}

void timer0_10()
{
T0CONbits.TMR0ON = 0; // timer off
T0CONbits.T0PS0 = 1; //1:4 PRESCALER
T0CONbits.T0PS1 = 0;
T0CONbits.T0PS2 = 0;
T0CONbits.PSA = 0;
T0CONbits.T0SE = 0;
T0CONbits.T0CS = 0; // CLK SOURCE
T0CONbits.T08BIT = 0; //16 BIT TIMER
RCONbits.IPEN = 1; //enable priority levels
INTCONbits.TMR0IE = 1; // enable interrupts, disable toan bo ngat chi cho phep ngat TMR0
INTCON2 = 0x04; //thiet lap TMR0 la ngat uu tien cao
INTCONbits.GIEH = 1; //cho phep ngat toan cuc
TMR0L = L;
TMR0H = H;
T0CONbits.TMR0ON = 1; // timer on
}
void main()
{
TRISD = TRISE = TRISBbits.TRISB4 = TRISBbits.TRISB5 = TRISAbits.TRISA4 =0;

/* TRISBbits.TRISB4 = 0;
TRISBbits.TRISB5 = 0;


TRISEbits.TRISE2 = 0;
TRISEbits.TRISE1 = 0;
TRISEbits.TRISE0 = 0;
TRISDbits.TRISD0 = 0;
TRISDbits.TRISD2 = 0;
TRISDbits.TRISD1 = 0;*/

LATD = 0X00;
timer0_10();
//-------------------------------------------------------
//vay tay chao
SERVO[2]=1920; //gap vai trai giua
SERVO[3]=1959; //gap vai phai giua
delay_ms(100);
SERVO[0]=1885;//tay trai xuong
delay_ms(100);
SERVO[1]=1870;//tay phai len
delay_ms(100);
// vay tay chao--------
for (i=0;i<3;i++)
{
SERVO[3]=1965; //gap vai phai len
SERVO[4]=1900; //quay dau sang trai
delay_ms(100);
SERVO[3]=1930; //gap vai phai xuong
SERVO[4]=1945; //quay dau sang phai
delay_ms(100);
}

while(1)
{
test_tay();

}

}


// vec to ngat uu tien cao

#pragma code InterruptVectorHigh=0x08
void InterruptVectorHigh(void)
{
_asm
goto ngatmuccao //nhay toi chuong trinh ngat
_endasm
}

//----------------------------------------------------------------------------
// chuong trinh ngat muc uu tien cao

#pragma code
#pragma interrupt ngatmuccao

void ngatmuccao() {

if (INTCONbits.TMR0IF) {
pulse_max++; // Pulse Max Increment
pulse_top++; // Pulse Top Increment

if (pulse_max >= set)
{
pulse_max=0;
pulse_top=0;
LATD = 0X00;
LATE = 0X00;

}

if (pulse_top == SERVO[0]) LATDbits.LATD0 =1; //vai trai
if (pulse_top == SERVO[1]) LATDbits.LATD1 =1; //canh trai
if (pulse_top == SERVO[2]) LATDbits.LATD2 =1;
if (pulse_top == SERVO[3]) LATDbits.LATD3 =1;
if (pulse_top == SERVO[4]) LATDbits.LATD4 =1;
if (pulse_top == SERVO[5]) LATDbits.LATD5 =1;
if (pulse_top == SERVO[6]) LATDbits.LATD6 =1;
if (pulse_top == SERVO[7]) LATDbits.LATD7 =1;

if (pulse_top == SERVO[8]) LATEbits.LATE2 =1; //vai phai
if (pulse_top == SERVO[9]) LATEbits.LATE1 =1; //canh phai
if (pulse_top == SERVO[10]) LATEbits.LATE0 =1;
if (pulse_top == SERVO[11]) LATAbits.LATA4 =1;
if (pulse_top == SERVO[12]) LATBbits.LATB5 =1;
if (pulse_top == SERVO[13]) LATBbits.LATB4 =1;
if (pulse_top == SERVO[14]) LATBbits.LATB3 =1;
if (pulse_top == SERVO[15]) LATBbits.LATB2 =1;

TMR0L = L;
TMR0H = H;
INTCONbits.TMR0IF = 0;
}
}

"

huyphuc92
16-06-2013, 12:07 PM
Đọc hiểu được cái code đầu bài :(
Nếu em không có căn bản về C, chưa từng viết code C cho VDK thì nên vào luồng nào để học???
Cấu trúc C em mù tịt :(

hunke92
17-07-2013, 04:14 PM
e bị lỗi thế này a jup e với
Error [192] D:\hi-tech\ADC1\ADC1.c; 20.1 undefined identifier "GODONE"
Error [192] D:\hi-tech\ADC1\ADC1.c; 35.1 undefined identifier "ANSEL"
Error [192] D:\hi-tech\ADC1\ADC1.c; 36.1 undefined identifier "ANSELH"
Error [192] D:\hi-tech\ADC1\ADC1.c; 38.1 undefined identifier "ANS3"
Error [192] D:\hi-tech\ADC1\ADC1.c; 46.1 undefined identifier "VCFG1"
Error [192] D:\hi-tech\ADC1\ADC1.c; 47.1 undefined identifier "VCFG0"
Error [192] D:\hi-tech\ADC1\ADC1.c; 59.1 undefined identifier "CHS3"
Error [192] D:\hi-tech\ADC1\ADC1.c; 164.1 undefined identifier "RBPU"
Error [192] D:\hi-tech\ADC1\ADC1.c; 165.1 undefined identifier "WPUB"

pucapuca123
17-07-2013, 05:42 PM
e bị lỗi thế này a jup e với
Error [192] D:\hi-tech\ADC1\ADC1.c; 20.1 undefined identifier "GODONE"
Error [192] D:\hi-tech\ADC1\ADC1.c; 35.1 undefined identifier "ANSEL"
Error [192] D:\hi-tech\ADC1\ADC1.c; 36.1 undefined identifier "ANSELH"
Error [192] D:\hi-tech\ADC1\ADC1.c; 38.1 undefined identifier "ANS3"
Error [192] D:\hi-tech\ADC1\ADC1.c; 46.1 undefined identifier "VCFG1"
Error [192] D:\hi-tech\ADC1\ADC1.c; 47.1 undefined identifier "VCFG0"
Error [192] D:\hi-tech\ADC1\ADC1.c; 59.1 undefined identifier "CHS3"
Error [192] D:\hi-tech\ADC1\ADC1.c; 164.1 undefined identifier "RBPU"
Error [192] D:\hi-tech\ADC1\ADC1.c; 165.1 undefined identifier "WPUB"

các bít này chưa được định nghĩa bạn mở file.h của con PIC bạn đang lập trình ra mà tìm các bít tương ứng chưa định nghĩa này

hunke92
17-07-2013, 08:21 PM
e tim k thấy file.h chỗ nào mong a chỉ cho e!

pucapuca123
18-07-2013, 09:47 AM
e tim k thấy file.h chỗ nào mong a chỉ cho e!

bạn vào ổ C tìm mục hitech PIC. sau đó vào mục include.h và sẽ có con PIC bạn cần dùng

transon5012
08-12-2013, 04:20 PM
đây là code đo độ rộng xung bằng ngắt RB0, từ đó tạo xung PWM bằng hàm delay hoặc CCP của Pic


mình copy >> pase vào trình dịch MPLAP-HITECH báo lỗi ,sao ko biên dịch được nhỉ ?

hiep_black
05-04-2014, 01:10 AM
là những cống hiến rất bổ ích, mình cũng mới bắt đầu làm quen với pic, cảm ơn rất nhiều nha ! ^^