View Single Post
Old 05-01-2007, 03:56 PM   #20
ngohaibac
Đệ tử 9 túi
 
ngohaibac's Avatar
 
Tham gia ngày: Oct 2005
Nơi Cư Ngụ: BKHN
Bài gửi: 231
:
Send a message via Yahoo to ngohaibac
Chuyển đổi ADC.

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 . 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:




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

Source code:
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
ngohaibac vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn