Nhập môn VĐK PIC với 16F877A

chivu

Kỹ sư
#1
Trong luồng này mình sẽ hướng dẫn những kiến thức cơ bản nhất về pic thông qua dòng pic 16f877a. Đây là những kiến thức rất sơ khai nên hy vọng sẽ giúp ích phần nào cho những bạn mới nhập môn cũng như khuyến cáo với những bạn đã có kiến thức về pic không nên tìm hiểu! Trong quá trình hướng dẫn không tránh được thiếu sót, rất mong được sự đóng góp của các pro để đây là luồng thông tin hữu ích khi các bạn tìm hiểu về pic đến với codientu.org.
Bài viết sẽ trình bày khá nhiều nên sẽ được chia làm một số phần cũng như được update liên tục vào #1
Bạn tải tài liệu đi kèm tại đây
pass: codientu.org (nếu có)

PHẦN 1: TỔNG QUAN VỀ PIC VÀ CÁC TÀI LIỆU ĐI KÈM
PIC là họ vi điều khiển mạnh, giàu tài nguyên về phần cứng và được microchip hỗ trợ nhiều tài liệu.
Chúng ta có thể dùng ngôn ngữ C hoặc ASM để lập trình cho vi điều khiển PIC. Tuy nhiên mình khuyên bạn nên lập trình PIC bằng ngôn ngữ C. Ngôn ngữ C sẽ hỗ trợ bạn tiếp cận vi điều khiển PIC nhanh nhất, không cần tốn nhiều thời gian nghiên cứu cấu trúc PIC mà bạn vẫn lập trình cho PIC một cách dễ dàng và sẵn sàng chia sẽ code với mọi người trên mạng vì đa số họ cũng lập trình cho PIC bằng ngôn ngữ C.
Và tất nhiên phần mềm biên dịch CCS lập trình cho họ vi điều khiển PIC bằng ngôn ngữ C. Nó là một trình biên dịch hỗ trợ ngôn ngữ C cho hầu hết các dòng vi điều khiển PIC. Bạn có thể tìm bản hướng dẫn sử dụng tại đây hoặc tài liệu đi kèm trong luồng này.
Phần mềm mô phỏng proteus 7.10 tại đây

PHẦN 2: CẤU TRÚC PHẦN CỨNG CỦA PIC
Bộ nhớ chương trình (ROM) và bộ nhớ dữ liệu (RAM) của PIC khá thoải mái (các bạn nhập môn không cần quan tâm quá nhiều vào vấn đề này).


Trong tài liệu đính kèm ở trên cấu trúc phần cứng đã được nêu khá cụ thể và chi tiết, các bạn có thể tự đọc. Trong luồng này mình sẽ nói nhiều hơn về các tập lệnh CCS sử dụng cho PIC 16f877a thông qua các ví dụ.

PHẦN 3: TẬP LÊNH CCS C CHO PIC 16F877A
1. Chỉ thị tiền xử lý

1. #INCLUDE
Cú pháp: #include<filename>
Khai báo chỉ định đường dẫn cho trình biên dịch
Ví dụ: #include<16f877a.h>
hoặc #include < C:\INCLUDES\CCSC\VIDU.C >

2.#BIT
Cú pháp: #bit name=x.y
Tạo biến 1bit có tên là name đặt ở byte x vị trí y. Thường dung để kiểm tra hoặc gán giá trị cho thanh ghi. Điểm khác so với dùng biến 1 bit từ khai báo int1 là: int1 tốn 1 bit bộ nhớ, còn #BIT thì không tốn thêm bộ nhớ do name chỉ danh định đại diện chi bit chỉ định ở biến x, thay đổi name (0/1) sẽ thay đổi giá trị tương ứng y -> thay đổi giá trị x.
Ví dụ: #bit TMR1IF=0x0B.2; => tạo biến 1bit tên TMR1IF đặt ở byte có địa chỉ 0x0B ở vị trí thứ 2.
3.#BYTE
Cú pháp: #byte name=x
Gán tên biến name cho địa chỉ x. name thường trùng với tên thanh ghi có địa chỉ x
Ví dụ: #byte portB=0x06;
4.#DEFINE
Cú pháp: #define name text
Dùng để khai báo một chuỗi hoặc số có tên là name
Ví dụ: #define constan 123456;
5.#USE:
Cú pháp: #use delay(clock=speed)
Dùng để khai báo tốc độ dao động của thạch anh và có chỉ thị này thì bạn mới sử dụng được các hàm trễ thời gian delay_ms hay delay_us
Cú pháp: #use fast_io(port)
Port là các cổng vào ra của PIC (từ A -> G)
Có chỉ thị này thì chúng ta có thể điều chỉnh các port chỉ với 1 lệnh như output_low(), input_high()...Chú ý: trong hàm main () bạn phải dùng hàm set_tris_x() để chỉ rõ chân vào ra thì chỉ thị trên mới có hiệu lực, nếu không chương trình sẽ chạy sai!
Ví dụ: #USE FAST_IO (A);
Bạn có thể tìm đọc thêm một số chỉ thị #USE I2C, #USE RS232 cũng như một số tiền xử lý khác trong tài liệu CCS C bản tiếng việt của Nguyễn Xuân Trường đi kèm ở trên.

2. Các hàm delay
Để sử dụng các hàm delay phải khai báo tiền xử lý như đã nói ở trên​
ví dụ: #use delay (clock=20000000);
Hàm delay không sử dụng bất kỳ một timer nào. Có 3 hàm phục vụ:​
1. Delay_cycles (count)
count: hằng số từ 0 - 255, là số chu kỳ lệnh. 1 chu kỳ lệnh bằng 4 chu kỳ máy nhé!​
ví dụ: delay_cycles (25); với tần số dao động thạch anh OSC=20MHZ thì hàm delay này 5us=5*10^-6s​
2. Delay_us (time)
Time là biến số thì giá trị từ 0-255, nếu là hằng số thì 0-65535.​
ví dụ:
int time=100;
delay_us (time); //delay 100us
delay_us (1000); //delay 1000us
3. Delay_ms (time)
Tương tự với delay_us nhưng với đơn vị là ms=10^-3s.​
3. Các hàm vào ra trong CCS C
Bao gồm các hàm sau:
Output_low() Output_high()
Output_bit() Input()
Ouput_X() Input_X()
Set_tris_X()

1 / Output_low ( pin ) , Output_high (pin ) :
Dùng để thiết lập ngõ ra mức 0 (low, 0v) hoặc mức 1 (high, 5v) cho chân PIC, pin chỉ vị trí của chân.
Có thể xuất xung dùng set_tris_x()#use fast_io
Ví dụ: output_high (pin_b0); //ngõ ra chân b0 là 0v
Delay_ms (1000); //tạo trễ 1000ms=1s
Output_low(pin_b0); //ngõ ra chân b0 là 5v
2. Output_bit ( pin , value ):
Pin: tên chân
Value: giá trị 0 hoặc 1
Hàm này cũng xuất ra chân giá trị 0 hoặc 1. Tương tự như hàm trên. Thường dùng khi giá trị ra tùy thuộc giá trị của 1 biến nào đó, hoặc muốn đảo lại giá trị ngõ ra trước đó.
Ví dụ:
Mã:
while (1 )
{
output_bit( pin_B0 , !x ) ;
Delay_ms(250 );
}
3. Input ( pin ):
Hàm cho giá trị đang có của chân pin là 0 hoặc 1. Giá trị 1bit
Ví dụ: m=input(pin_B1); //giá trị m bằng 0 hoặc 1
4. Output_X ( value ) :
Hàm xuất giá trị 1 byte (8bit) ra port x, tất cả các chân của port đều là ngõ ra
Ví dụ:
Mã:
Output_B ( 212 ) ; // xuất giá trị 11010100 ra port B
Output_A ( 10101010b ) ; // xuất giá trị 10101010 ra port A
5. Input_X ( ) :
Hàm trả về giá trị 8bit (1byte) là giá trị đang có của port tên X (A -> G).
Ví dụ: m=input_A
6. Set_tris_X ( value ) :
Hàm này dùng để định nghĩa chân IO (vào/ra) cho 1 port là ngõ vào hay ngõ ra. Chỉ dùng được khi đã khai báo tiền xử lý #use_fast_io.
Sử dụng #byte để tạo 1 biến chỉ đến port và thao tác trên biến này chính là thao tác trên port đó.
Value là giá trị 8 bit. Mỗi bit đại diện cho 1 chân, bit=0 thì chân đó là ngõ ra còn bit=1 chân đó là ngõ vào
ví dụ : Đoạn mã sau cho phép thao tác trên port b 1 cách dễ dàng:
Mã:
#include < 16F877.h >
#use delay(clock=20000000)
#use Fast_IO( B )
#byte portB = 0x6 // 16F877 port b ở địa chỉ 6h (portB ở đây là biến chỉ thanh ghi ở địa chỉ //0x6 chứ CCS C không có từ khóa portB ở địa chỉ 0x6, ta có thể đổi portA = 0x6 vẫn ok //nhưng sẽ gây nhầm lẫn lung tung và không thống nhất với các ký hiệu của nhà sản xuất và //người sử dụng!).
#bit B0 = portB. 0 // bit ở chân B0 có tên biến là B0
Main()
{
Set_tris_b (0); // portb = 00000000b => tất cả các chân port b là ngõ ra.
……..
}
4. Hàm sử dụng trong các TIMER
Có 3 TIMER là TIMER0, TIMER1, TIMER2. Các hàm sử dụng cho các TIMER các bạn có thể tham khỏa trong tài liệu đính kèm. Trong các ví dụ cụ thể mình sẽ cố gắng giải thích các hàm này cho các bạn dễ hình dung hơn.
to be continued #2 :49.jpg::49.jpg::49.jpg:
 

chivu

Kỹ sư
#2
5. Các hàm phục vụ ngắt
- ENABLE_INTERRUPTS( level) // khai báo ngắt
Level: //các dạng ngắt
+GLOBAL : cho phép ngắt toàn cục
+INT_TIMER0 : ngắt do tràn TIMER0
+INT_TIMER1 : ngắt do tràn Timer1
+INT_TIMER2 : ngắt do tràn Timer2
+INT_RB : có thay đổi 1 trong các chân RB4 _ RB7
+INT_EXT : ngắt ngoài trên chân RB0
Chú ý : sau khi khai báo trên thì để vào chương trình ngắt cần khai báo
#INT_.....
ví dụ:
Mã:
#INT_TIMER1
Void ngat_Timer1( )
{
//chương trình ngắt viết ở đây
}
6. Điều chế độ rộng xung PWM

Để giải quyết vấn đề việc điều xung PWM bằng phần mềm chiếm phần lớn thời gian hoạt động của vi điều khiển, PIC16F877A có hỗ trợ 2 kênh điều xung bằng phần cứng ở 2 chân C1(CCP2)C2(CCP1) sử dụng TIMER2. Nghĩa là, khi ta khai báo điều xung PWM ở một tần số và duty cycle nào đó thì vi điều khiển sẽ thực hiện công việc xuất xung một cách liên tục và tự động cho đến khi ta thay đổi các giá trị đã khai báo. Khi đó, ta có thể làm các công việc khác một cách dễ dàng mà không phải mất thời gian cho việc duy trì xung PWM.
Các hàm hỗ trợ việc điều xung bằng phần cứng của CCS:
Ghi chú: Chỉ đề cập đến các đối số của các hàm được phục vụ cho việc điều xung PWM.
+ setup_timer_2 (mode, period, postscale)
mode: T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
period: 0-255
postscale: 1
Tần số điều xung PWM:
f = fosc / [ 4*mode*(period+1) ]

+ setup_ccp1(mode)setup_ccp2(mode)
mode:
CCP_PWM: chọn chế độ PWM.
CCP_OFF: tắt chế độ PWM.
+ set_pwm1_duty(value)set_pwm2_duty(value)
Nếu value là giá trị kiểu int 8bit:
duty_cycle = value / ( period+1 )


Nếu value là giá trị long int 16bit:
duty_cycle = value&1023 / [4*( period+1 )]

Nếu không cần điều xung quá “mịn” thì nên điều xung ở giá trị value 8bit cho đơn giản.
Ví dụ: Ta muốn điều xung PWM với tần số 10kHz với tần số thạch anh (fosc) sử dụng là 20MHz (value 8bit).
f=fosc/[4*mode*(period+1)]


<=> 10000 =20000000/[ 4*mode*(period+1) ] <=> mode(period+1) = 500

Với mode = [1,4,16] và period = 0-255 ta có thể chọn:
mode = 4; period = 124
mode = 16; period = 32
Để cho việc điều xung được “mịn” (chọn được nhiều giá trị duty cycle) ta chọn mode = 4 và period = 124.
Như vậy, để duty_cycle từ 0% đến 100% ta cho value từ 0 đến 125.
value = 30 => duty_cycle = 30 / ( 124+1 ) = 0.32 = 32%
value = 63 => duty_cycle = 63 / ( 124+1 ) = 0.504 = 50.4%
value = 113 => duty_cycle = 113 / ( 124+1 ) = 0.904 = 90.4%
ví dụ:
Code:
setup_timer_2(T2_DIV_BY_4,124,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(30);
PHẦN 4: CÁC VÍ DỤ KÈM MÔ PHỎNG PROTEUS
1.Xuất tín hiệu 0/1 ra các chân




Mã:
#INCLUDE<16F877A.h> //KHAI BAO DEVICE CHO PIC
#FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
/*
XT: SU DUNG THACH ANH TAN SO THAP (=4MHZ)
NOWDT:KHONG SU DUNG CHE DO WATCH DOG TIMER
PUT(POWER UP TIMER): CHON CHE DO LAM VIEC CHO PIC KHI DIEN AP DA ON DINH
NOPROTECT : KHONG CHO PHEP DOC LAI MA CHUONG TRINH TRONG CHIP
NOBROWNOUT : KHONG RESET LAI PIC KHI BI SUT AP
NOLVP(LOW VOLTAGE PROGRAMMING) : ??
*/
#USE DELAY(CLOCK=4000000) //GIA TRI OSC MA BAN DUNG
#USE FAST_IO(B)
VOID MAIN()
{
SET_TRIS_B(0); //THIET LAP CAC CHAN CUA PORTA LA CAC CHAN XUAT DU LIEU
WHILE(TRUE) //TAO VONG LAP VO TAN
{
OUTPUT_HIGH(PIN_B0); //XUAT GIA TRI 1 RA CHAN RB0
DELAY_MS(500); //TAO TRE 0,5s
OUTPUT_LOW(PIN_B0); //XUAT GIA TRI 0 RA CHAN RB0
DELAY_MS(500);
OUTPUT_B(255); //DUA GIA TRI 1 RA CAC CHAN CUA PORTB
DELAY_MS(500);
OUTPUT_B(0); //DUA GIA TRI 0 RA CAC CHAN CUA PORTB
DELAY_MS(500);
}
}
2. Giao tiếp với nút bấm

Mã:
#INCLUDE<16F877A.H>
#FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
#USE DELAY(CLOCK=4000000)
#USE FAST_IO(B)
#BYTE PORTB=0x06
#BIT BUTTON=PORTB.7
#BIT LED=PORTB.6
VOID MAIN()
{
SET_TRIS_B(0b10111111); //LAP CHE CHO PIN_B6 LA XUAT CON CAC CHAN KHAC LA NHAP
WHILE(TRUE)
{
IF(BUTTON==0) //KIEM TRA NUT BAM
{
LED=1; //BAT DEN
DELAY_MS(1000);
LED=0; //TAT DEN
}
}
}
3. Delay dùng vòng lặp
Mã:
#INCLUDE<16F877A.H>
#FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
#USE DELAY(CLOCK=4000000)
#BYTE INTCON=0x0B
#BYTE PIR1=0x0C
#BYTE T1CON=0x10
#BIT TMR1ON=T1CON.0 //KHOI DONG TIMER1
#BIT TMR1IF=PIR1.0 //CO TRAN TIMER1
#BIT INTF=INTCON.1 //CO NGAT
VOID DELAY(INT8 TIMER)
{
WHILE(TIMER--)
{
TMR1ON=1;
WHILE(TMR1IF==0);
TMR1ON=0;
TMR1IF=0;
}
}
VOID MAIN()
{
WHILE(TRUE)
{
OUTPUT_HIGH(PIN_C4);
DELAY(100);
OUTPUT_LOW(PIN_C4);
DELAY(100);
}
}
//TUONG TU VOI CAC TIMER0 VA TIMER2 CAC BAN CO THE XEM DATASHEET DE BIET THEM VE DIA
CHI
// CAC THANH GHI CHUC NANG CUA CHUNG
to be continued #3 :49.jpg::49.jpg::49.jpg:
 

chivu

Kỹ sư
#3
4. Delay dùng TIMER không dùng ngắt
Mã:
#INCLUDE<16F877A.H>
#FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
#USE DELAY(CLOCK=4000000)
#BYTE INTCON=0x0B
#BYTE PIR1=0x0C
#BYTE T1CON=0x10
#BYTE T2CON=0x12
#BIT TMR1ON=T1CON.0 //KHOI DONG TIMER1
#BIT TMR1IF=PIR1.0 //CO TRAN TIMER1
#BIT TMR0IF=INTCON.2 //CO TRAN TIMER0
#BIT TMR2ON=T2CON.2 //KHOI DONG TIMER2
#BIT TMR2IF=PIR1.1 //CO TRAN TIMER2
VOID MAIN()
{
SET_TRIS_E(0);
SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_2); //SU DUNG TAN SO DAO DONG NOI VA BO CHIA
TAN 1:2
SET_TIMER0(0); //DAT GIA TRI THANH GHI DINH THOI TMR0=0
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_4); //SU DUNG TAN SO DAO DONG NOI VA BO CHIA TAN
1:4
SET_TIMER1(0); //DAT GIA TRI THANH GHI DINH THOI TMR1=0
SETUP_TIMER_2(T2_DIV_BY_16,255,1); //SU DUNG TAN SO DAO DONG NOI VA BO CHIA TAN 1:16
SET_TIMER2(0); //DAT GIA TRI THANH GHI DINH THOI TMR2=0
TMR0IF=TMR1IF=TMR2IF=0; //XOA CAC CO TRAN
WHILE(TRUE)
{
IF(TMR0IF==1) //KIEM TRA CO TRAN TIMER0
{
OUTPUT_HIGH(PIN_E0);
DELAY_MS(50);
OUTPUT_LOW(PIN_E0);
TMR0IF=0;
}
ELSE IF(TMR1IF==1) //KIEM TRA CO TRAN TIMER1
{
OUTPUT_HIGH(PIN_E1);
DELAY_MS(50);
OUTPUT_LOW(PIN_E1);
TMR1IF=0;
}
ELSE IF(TMR2IF==1) //KIEM TRA CO TRAN TIMER2
{
 
OUTPUT_HIGH(PIN_E2);
DELAY_MS(50);
OUTPUT_LOW(PIN_E2);
TMR2IF=0;
}
}
}
5. Delay dùng TIMER có dùng ngắt
Mã:
#INCLUDE<16F877A.H>
#FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
#USE DELAY(CLOCK=4000000)
#BYTE PORTB=0x06
#BYTE PORTC=0x07
#BYTE PORTD=0x08
#INT_TIMER0 //CHUONG TRINH NGAT TIMER0
VOID NGAT_TIMER0()
{
PORTB=0b10101010;
DELAY_MS(200);
PORTB=0b01010101;
}
#INT_TIMER1 //CHUONG TRINH NGAT TIMER1
VOID NGAT_TIMER1()
{
PORTC=0b11110000;
DELAY_MS(200);
PORTC=0b00001111;
}
#INT_TIMER2 //CHUONG TRINH NGAT TIMER2
VOID NGAT_TIMER2()
{
PORTD=0b11001100;
DELAY_MS(200);
PORTD=0b00001111;
}
VOID MAIN()
{
SET_TRIS_B(0);
SET_TRIS_C(0);
SET_TRIS_D(0);
ENABLE_INTERRUPTS(GLOBAL); //CHO PHEP TAT CA CAC NGAT HOAT DONG
ENABLE_INTERRUPTS(INT_TIMER0); //CHO PHET NGAT BANG TIMER0
ENABLE_INTERRUPTS(INT_TIMER1); //CHO PHET NGAT BANG TIMER1
ENABLE_INTERRUPTS(INT_TIMER2); //CHO PHET NGAT BANG TIMER2
SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_1);
SET_TIMER0(0);
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_4);
SET_TIMER1(0);
SETUP_TIMER_2(T2_DIV_BY_16,255,1);
SET_TIMER2(0);
WHILE(TRUE); //KHONG LAM GI CA CHO NGAT
}
Ngoài ra còn một số ví dụ khác về sử dụng chế độ COUNTER (chế độ đếm), chế độ điều xung PWM, ví dụ sử dụng ngắt ngoài cũng như hướng dẫn mô phỏng PROTEUS các bạn có thể đọc thêm ở trong tài liệu đính kèm ở trên! Nếu còn thắc mắc, chưa hiểu chỗ nào mình sẽ cố gắng giải thích cụ thể! những ca khó sẽ được chuyển lên tuyến trên! Chúc các bạn làm quen với PIC một cách thuận lợi nhất!
Thân!
 

The Kid

Kỹ sư
#4
các bạn ơi, mình viết chương trình cho máy đếm tần trên nền asm như sau (các bít cấu hình mình đã chọn trong MPLAP)
Mã:
PROCESSOR 16F877A
 
INCLUDE <P16F877A.INC>
 
DIGIT0 EQU 0X21
 
DIGIT1 EQU 0X22
 
DIGIT2 EQU 0X23
 
DIGIT3 EQU 0X24
 
DIGIT4 EQU 0X25
 
DIGIT5 EQU 0X26
 
BUFF0 EQU 0X27
 
BUFF1 EQU 0X28
 
BUFF2 EQU 0X29
 
BUFF3 EQU 0X31
 
BUFF4 EQU 0X32
 
BUFF5 EQU 0X33
 
CNTW EQU 0X34
 
CNT1 EQU 0X35
 
CNT2 EQU 0X36
 
CNT EQU 0X37
 
WORKA EQU 0X41
 
; BAT DAU CHUONG TRINH
 
ORG 0X00
 
GOTO START
 
START
 
BCF STATUS,RP1
 
BSF STATUS,RP0
 
MOVLW 0X00
 
MOVWF TRISB
 
CLRF PIE1
 
MOVLW 0X00
 
MOVWF TRISD
 
MOVLW 0XFF
 
MOVWF TRISC
 
CLRF OPTION_REG
 
BSF OPTION_REG,7
 
BCF STATUS,RP0
 
MOVLW 0XC0
 
MOVWF DIGIT0
 
MOVWF DIGIT1
 
MOVWF DIGIT2
 
MOVWF DIGIT3
 
MOVWF DIGIT4
 
MOVWF DIGIT5
 
CLRF BUFF0
 
CLRF BUFF1
 
CLRF BUFF2
 
CLRF BUFF3
 
CLRF BUFF4
 
CLRF BUFF5
 
CLRF WORKA
 
MOVLW 0X0E
 
MOVWF T1CON ; THIET LAP THONG SO CHO BO DEM TMR1 : CHAN DEM TU RC0, HE SO CHIA =1, DEM KO DONG BO
 
CLRF PIR1
 
LOOP
 
CLRF CNT
 
CLRF TMR1H
 
CLRF TMR1L
 
BCF PIR1,TMR1IF
 
BSF T1CON,TMR1ON
 
CALL REFRESSH ; BAT DAU DEM
 
CALL REFRESSH
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
BCF T1CON,TMR1ON ; TAT BO DEM DE XU LY KET QUA DEM
 
MOVF CNTW,0
 
MOVWF CNT
 
MOVF TMR1H,0
 
MOVWF CNT1
 
MOVF TMR1L,0
 
MOVWF CNT2
 
BTFSC PIR1,TMR1IF
 
INCF CNT
 
MOVLW 0X05
 
SUBWF CNT,0
 
BTFSC STATUS,C
 
GOTO OVER
 
BTFSC CNT,2
 
GOTO CV1
 
GOTO CV2
 
CV1
 
MOVLW d'2'
 
MOVWF BUFF0
 
MOVLW d'6'
 
MOVWF BUFF1
 
MOVLW d'2'
 
MOVWF BUFF2
 
MOVLW d'1'
 
MOVWF BUFF3
 
MOVLW d'4'
 
MOVWF BUFF4
 
MOVLW d'4'
 
MOVWF BUFF5
 
CV2
 
BTFSS CNT,1
 
GOTO CV3
 
MOVLW d'1'
 
MOVWF BUFF0
 
MOVLW d'3'
 
MOVWF BUFF1
 
MOVLW d'1'
 
MOVWF BUFF2
 
MOVLW d'0'
 
MOVWF BUFF3
 
MOVLW d'7'
 
MOVWF BUFF4
 
MOVLW d'2'
 
MOVWF BUFF5 ; 13170
 
CV3
 
BTFSS CNT,0
 
GOTO CV4
 
MOVLW d'6'
 
ADDWF BUFF1,1
 
MOVLW d'5'
 
ADDWF BUFF2,1
 
MOVLW d'5'
 
ADDWF BUFF3,1
 
MOVLW d'3'
 
ADDWF BUFF4,1
 
MOVLW d'6'
 
ADDWF BUFF5, 1 ;65535
 
CV4
 
BTFSS CNT1,7
 
GOTO CV5
 
MOVLW d'3'
 
ADDWF BUFF1
 
MOVLW d'2'
 
ADDWF BUFF2
 
MOVLW d'7'
 
ADDWF BUFF3
 
MOVLW d'6'
 
ADDWF BUFF4
 
MOVLW d'8'
 
ADDWF BUFF5 ;32768
 
CV5
 
BTFSS CNT1,6
 
GOTO CV6
 
MOVLW d'1'
 
ADDWF BUFF1
 
MOVLW d'6'
 
ADDWF BUFF2
 
MOVLW d'3'
 
ADDWF BUFF3
 
MOVLW d'8'
 
ADDWF BUFF4
 
MOVLW d'4'
 
ADDWF BUFF5 ;16384
 
CV6
 
BTFSS CNT1,5
 
GOTO CV7
 
MOVLW d'8'
 
ADDWF BUFF2
 
MOVLW d'1'
 
ADDWF BUFF3
 
MOVLW d'9'
 
ADDWF BUFF4
 
MOVLW d'2'
 
ADDWF BUFF5 ;8912
 
CV7
 
BTFSS CNT1,4
 
GOTO CV8
 
MOVLW d'4'
 
ADDWF BUFF2
 
; MOVLW d'0'
 
; ADDWF BUFF3
 
MOVLW d'9'
 
ADDWF BUFF4
 
MOVLW d'6'
 
ADDWF BUFF5 ;4096
 
CV8
 
BTFSS CNT1,3
 
GOTO CV9
 
MOVLW d'2'
 
ADDWF BUFF2
 
; MOVLW d'0'
 
; ADDWF BUFF3
 
MOVLW d'4'
 
ADDWF BUFF4
 
MOVLW d'8'
 
ADDWF BUFF5
 
CV9
 
BTFSS CNT1,2
 
GOTO CV10
 
MOVLW d'1'
 
ADDWF BUFF2
 
; MOVLW d'0'
 
; ADDWF BUFF3
 
MOVLW d'2'
 
ADDWF BUFF4
 
MOVLW d'4'
 
ADDWF BUFF5
 
CV10
 
BTFSS CNT1,1
 
GOTO CV11
 
MOVLW d'5'
 
ADDWF BUFF3
 
MOVLW d'1'
 
ADDWF BUFF4
 
MOVLW d'2'
 
ADDWF BUFF5
 
CV11
 
BTFSS CNT1,0
 
GOTO CV12
 
MOVLW d'2'
 
ADDWF BUFF3
 
MOVLW d'5'
 
ADDWF BUFF4
 
MOVLW d'6'
 
ADDWF BUFF5
 
CV12
 
BTFSS CNT2,7
 
GOTO CV13
 
MOVLW d'1'
 
ADDWF BUFF3
 
MOVLW d'2'
 
ADDWF BUFF4
 
MOVLW d'8'
 
ADDWF BUFF5
 
CV13
 
BTFSS CNT2,6
 
GOTO CV14
 
MOVLW d'6'
 
ADDWF BUFF4
 
MOVLW d'4'
 
ADDWF BUFF5
 
CV14
 
BTFSS CNT2,5
 
GOTO CV15
 
MOVLW d'3'
 
ADDWF BUFF4
 
MOVLW d'2'
 
ADDWF BUFF5
 
CV15
 
BTFSS CNT2,4
 
GOTO CV16
 
MOVLW d'1'
 
ADDWF BUFF4
 
MOVLW d'6'
 
ADDWF BUFF5
 
CV16
 
BTFSS CNT2,3
 
GOTO CV17
 
MOVLW d'8'
 
ADDWF BUFF5
 
CV17
 
BTFSS CNT2,2
 
GOTO CV18
 
MOVLW d'4'
 
ADDWF BUFF5
 
CV18
 
BTFSS CNT2,1
 
GOTO CV19
 
MOVLW d'2'
 
ADDWF BUFF5
 
CV19
 
BTFSS CNT2,0
 
GOTO CVR
 
MOVLW d'1'
 
ADDWF BUFF5,1
 
CVR
 
MOVLW 0X0A
 
SUBWF BUFF5,0
 
BTFSS STATUS,C
 
GOTO CR1
 
MOVLW 0X0A
 
SUBWF BUFF5,1
 
INCF BUFF4
 
GOTO CVR
 
CR1
 
MOVLW 0X0A
 
SUBWF BUFF4,0
 
BTFSS STATUS,C
 
GOTO CR2
 
MOVLW 0X0A
 
SUBWF BUFF4,1
 
INCF BUFF3
 
GOTO CR1
 
CR2
 
MOVLW 0X0A
 
SUBWF BUFF3,0
 
BTFSS STATUS,C
 
GOTO CR3
 
MOVLW 0X0A
 
SUBWF BUFF3,1
 
INCF BUFF2,1
 
GOTO CR2
 
CR3
 
MOVLW 0X0A
 
SUBWF BUFF2,0
 
BTFSS STATUS,C
 
GOTO CR4
 
MOVLW 0X0A
 
SUBWF BUFF2,1
 
INCF BUFF1
 
GOTO CR3
 
CR4
 
MOVLW 0X0A
 
SUBWF BUFF1,0
 
BTFSS STATUS,C
 
GOTO DOCKQ
 
MOVLW 0X0A
 
SUBWF BUFF1,1
 
INCF BUFF0
 
GOTO CR4
 
DOCKQ
 
MOVLW 0X01
 
MOVWF PCLATH
 
MOVF BUFF0,0
 
CALL TABLE
 
MOVWF DIGIT0
 
MOVF BUFF1,0
 
CALL TABLE
 
MOVWF DIGIT1
 
MOVF BUFF2,0
 
CALL TABLE
 
MOVWF DIGIT2
 
MOVF BUFF3,0
 
CALL TABLE
 
MOVWF DIGIT3
 
MOVF BUFF4,0
 
CALL TABLE
 
MOVWF DIGIT4
 
MOVF BUFF5,0
 
CALL TABLE
 
MOVWF DIGIT5
 
CLRF BUFF0
 
CLRF BUFF1
 
CLRF BUFF2
 
CLRF BUFF3
 
CLRF BUFF4
 
CLRF BUFF5
 
GOTO LOOP
 
TABLE
 
ADDWF PCL,1
 
RETLW 0XC0
 
RETLW 0XF9
 
RETLW 0XA4
 
RETLW 0XB0
 
RETLW 0X99
 
RETLW 0X92
 
RETLW 0X82
 
RETLW 0XF8
 
RETLW 0X80
 
RETLW 0X90
 
REFRESSH
 
BSF PORTB,0
 
BCF PORTB,5
 
MOVF DIGIT0,0
 
MOVWF PORTD
 
NOP
 
CALL TMRCHK
 
BSF PORTB,5
 
BCF PORTB,4
 
MOVF DIGIT1,0
 
MOVWF PORTD
 
BCF PORTD,7
 
CALL TMRCHK
 
BSF PORTB,4
 
BCF PORTB,3
 
MOVF DIGIT2,0
 
MOVWF PORTD
 
NOP
 
CALL TMRCHK
 
BSF PORTB,3
 
BCF PORTB,2
 
MOVF DIGIT3,0
 
MOVWF PORTD
 
NOP
 
CALL TMRCHK
 
BSF PORTB,2
 
BCF PORTB,1
 
MOVF DIGIT4,0
 
MOVWF PORTD
 
BCF PORTD,7
 
CALL TMRCHK
 
BSF PORTB,1
 
BCF PORTB,0
 
MOVF DIGIT5,0
 
MOVWF PORTD
 
NOP
 
CALL TMRCHK
 
RETURN
 
TMRCHK
 
MOVLW 0X29
 
MOVWF WORKA
 
nop
 
nop
 
KT BTFSS PIR1,TMR1IF
 
GOTO XX1 ;3
 
INCF CNTW
 
BCF PIR1,TMR1IF
 
GOTO XX2
 
XX1
 
NOP
 
NOP ;5
 
XX2
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
NOP
 
DECFSZ WORKA
 
GOTO KT
 
RETURN
 
OVER
 
MOVLW 0XC0
 
MOVWF DIGIT0
 
MOVLW 0XB1
 
MOVWF DIGIT2
 
MOVLW 0X86
 
MOVWF DIGIT3
 
MOVLW 0XCE
 
MOVWF DIGIT4
 
MOVLW 0XFF
 
MOVWF DIGIT1
 
MOVWF DIGIT5
 
goto LOOP
 
END
 
;
khi chạy trên proteus thì chạy ở tần số vào chỉ được đến 20Khz, trên nữa là mô phỏng chậm như rùa bò ấy. nó báo là " simulation is not running in real time due to excessive cpu"

Đây là hình mình chụp khi tần số vào la 7.1 Khz



mình lập trình để đếm tối đa đến 32 Mhz mà không thể mô phỏng được. Mong các bạn có thể giúp mình một tìm cách khắc phục điểm này nha
 

sgesvn

Moderator
Thành viên BQT
#6
các bạn ơi, mình viết chương trình cho máy đếm tần trên nền asm như sau (các bít cấu hình mình đã chọn trong MPLAP)

khi chạy trên proteus thì chạy ở tần số vào chỉ được đến 20Khz, trên nữa là mô phỏng chậm như rùa bò ấy. nó báo là " simulation is not running in real time due to excessive cpu"

Đây là hình mình chụp khi tần số vào la 7.1 Khz

mình lập trình để đếm tối đa đến 32 Mhz mà không thể mô phỏng được. Mong các bạn có thể giúp mình một tìm cách khắc phục điểm này nha
  • Tất các các code bạn phải đưa vào thẻ code chứ để như thế chẳng ai muốn đọc nữa
  • " simulation is not running in real time due to excessive cpu" là do khả năng tính toán thời gian trên PC của bạn nên Proteus không thể chạy với thời gian thực vì CPU sẽ quá tải. Khi chạy thật trên vi điều khiển mạch của bạn vẫn hoạt động bình thường
  • Bạn đưa code mà không đưa file mô phỏng đính kèm thì đúng là khó giúp
Híc, làm sao để post được hình ảnh hả các bạn
Bạn nên đọc rõ các hướng dẫn sử dụng của diễn đàn:
hướng dẫn - Đưa Ảnh Và Video Lên Diễn Đàn. Cộng đồng Cơ điện tử Việt Nam
--------------
Chúc vui!
 

BuiBachTuanAnh

Quản trị viên
Thành viên BQT
#8
hình trên là mình mô phỏng 7.1 Khz, còn đây là 15k, chữ số mất dần. trên nữa thì than ôi
Ở đây vấn đề của bạn nói đến là thuật toán. Nếu ở tần số thấp đã chạy ok chứng tỏ thuật toán không sai. Khi bạn đưa lên tần số cao thì cái này do đáp ứng thời gian thực của PC và phần mềm mô phỏng không khớp nhau nên sẽ bị lỗi " simulation is not running in real time due to excessive cpu". Khi chạy trên mạch thật sẽ không vấn đề gì cả.
--------------------------
Nếu bạn đính kèm file mô phỏng thì mình có thể thử giúp bạn trên máy của mình xem sao?
Bạn nên đọc thêm: hướng dẫn - Yêu Câu Sự Trợ Giúp Từ Thành Viên Diễn Đàn Cộng đồng Cơ điện tử Việt Nam
 
#9
Mã:
#INCLUDE<16F877A.H>
 
#FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
 
#USE DELAY(CLOCK=4000000)
 
#BYTE INTCON=0x0B // ????
 
#BYTE PIR1=0x0C //???
 
#BYTE T1CON=0x10 ////?????
 
#BIT TMR1ON=T1CON.0 //KHOI DONG TIMER1
 
#BIT TMR1IF=PIR1.0 //CO TRAN TIMER1
 
#BIT INTF=INTCON.1 //CO NGAT
 
VOID DELAY(INT8 TIMER)
 
{
 
WHILE(TIMER--)
 
{
 
TMR1ON=1;
 
WHILE(TMR1IF==0);
 
TMR1ON=0;
 
TMR1IF=0;
 
}
 
}
 
VOID MAIN()
 
{
 
WHILE(TRUE)
 
{
 
OUTPUT_HIGH(PIN_C4);
 
DELAY(100);
 
OUTPUT_LOW(PIN_C4);
 
DELAY(100);
 
}
 
}
 
//TUONG TU VOI CAC TIMER0 VA TIMER2 CAC BAN CO THE XEM DATASHEET DE BIET THEM VE DIA
 
CHI
 
// CAC THANH GHI CHUC NANG CUA CHUNG

anh giải thích ý nghĩa mây lệnh trên giúp em vói ( chỗ dấu ? ý)
 
#10
Đó chỉ là các define do user đặt ra để tiện trong quá trình code thôi bạn ạ!
VD: bạn define
#define on 1
thì sau này bạn viết code ở dưới chỉ cần viết:
led1=on;
thế là LED sẽ sáng( ko cần phải viết là LED1=1), cách viết này giúp ta quản lý code tốt hơn rất nhiều, vì sau này muốn edit code hay debug chỉ cần edit những define đầu tiên, và nếu đúng hơn bạn có thể lưu hết các define bên file main.h ( mặc định tạo ra khi sử dụng CCS-C vì code này nhìn là biết dùng CCS).
Như vậy tương tự ở trên là khai báo các Byte tương ứng với các thanh ghi của Timer1 để sử dụng timer ko cần phải viết lại các giá trị thanh ghi, ở dưới là define các bit tương ứng với các trạng thái của Timer1.
Regard.
 

Quảng cáo Google

Quảng cáo Google