مطالب علمی

ساعت دیجیتال با AVR و سون سگمنت

کار با سون سگمنت در این پروژه و نحوه برنامه نویسی اون به طور کامل شرح داده شده به طوری که می تونید از کدهای مربوط به سون سگمنت در پروژه در میکروکنترلر های مختلف و پروژه ای مختلف استفاده کنید. سعی شده کد  به صورت خط به خط و کامل توضیح داده شود.

عملکرد ساعت دیجیتال طراحی شده:

عملکرد این مدار به این صورت است که با وصل شدن برد به منبع تغذیه ساعت از “00:00:00” شروع به کار می کند. به وسیله 2 دکمه فشاری می توان ساعت و دقیقه را تنظیم کرد. دکمه SW1 برای تنظیم دقیقه و دکمه ی SW2 برای تنظیم ساعت به کار می رود.

شماتیک لازم برای راه اندازی ساعت دیجیتال با AVR و سون سگمنت:

این برنامه به صورت صحیح و بدون تغییر در میکروکنترلر های ATmega32 و ATmega16 کار می کند.

ساعت دیجیتال با AVR و سون سگمنت

توجه مهم: برای کارکرد صحیح مدار باید اسیلاتور داخلی میکروکنترلر روی 4MHZ تنظیم شده باشد.

برنامه ی ساعت دیجیتال با ATmega32:

/*
 * DigitalClock.c
 * Written in AVR Studio 5
 * Compiler: AVR GNU C Compiler (GCC)
 *
 * Created: 12/10/2011 1:17:19 PM
 * Author:	AVR Tutorials
 * Website:	www.AVR-Tutorials.com
 */ 
#define F_CPU	4000000UL
#include <avr/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
#define SegDataPort		PORTB
#define SegDataPin		PINB
#define SegDataDDR		DDRB
 
#define SegCntrlPort	PORTC
#define SegCntrlPin		PINC
#define SegCntrlDDR		DDRC
 
 
/*Global Variables Declarations*/
unsigned char hours = 0;
unsigned char minutes = 0;
unsigned char seconds = 0;
 
 
/*Function Declarations*/
/*****************************************************************************/
/*Decimal Digit (0-9) to Seven Segment Values Encoder*/
unsigned char DigitTo7SegEncoder(unsigned char digit, unsigned char common);
 
/*Timer Counter 1 Compare Match A Interrupt Service Routine/Interrupt Handler*/
ISR(TIMER1_COMPA_vect);
 
 
/*Main Program*/
/*****************************************************************************/
int main(void)
{
    SegDataDDR = 0xFF;
	SegCntrlDDR = 0x3F;
	SegCntrlPort = 0xFF;
 
	TCCR1B = (1<<CS12|1<<WGM12);
	OCR1A = 15625-1;
	TIMSK = 1<<OCIE1A;
	sei();
 
 
	while(1)
    {
        /* Set Minutes when SegCntrl Pin 6 Switch is Pressed*/
		if((SegCntrlPin & 0x40) == 0 )
		{	
			_delay_ms(200);
			if(minutes < 59)
				minutes++;
			else
				minutes = 0;
		}
        /* Set Hours when SegCntrl Pin 7 Switch is Pressed*/			
		if((SegCntrlPin & 0x80) == 0 )
		{	
			_delay_ms(200);
			if(hours < 23)
				hours++;
			else
				hours = 0;
		}			
 
		SegDataPort = DigitTo7SegEncoder(seconds%10,1);
		SegCntrlPort = ~0x01;
		SegDataPort = DigitTo7SegEncoder(seconds/10,1); 
		SegCntrlPort = ~0x02;
		SegDataPort = DigitTo7SegEncoder(minutes%10,1);
		SegCntrlPort = ~0x04;
		SegDataPort = DigitTo7SegEncoder(minutes/10,1); 
		SegCntrlPort = ~0x08;
		SegDataPort = DigitTo7SegEncoder(hours%10,1); 
		SegCntrlPort = ~0x10;
		SegDataPort = DigitTo7SegEncoder(hours/10,1);
		SegCntrlPort = ~0x20;
 
    }
	return 0;
}
 
/*
* Function Description:
* Encode a Decimal Digit 0-9 to its Seven Segment Equivalent.
*
* Function Arguments:
* digit - Decimal Digit to be Encoded
* common - Common Anode (0), Common Cathode(1)
* SegVal - Encoded Seven Segment Value 
*
* Connections:
* Encoded SegVal is return in the other G-F-E-D-C-B-A that is A is the least
* significant bit (bit 0) and G bit 6.
*/
unsigned char DigitTo7SegEncoder(unsigned char digit, unsigned char common)
{
	unsigned char SegVal;
 
	switch(digit)	
	{	
		case 0:	if(common == 1)	SegVal = 0b00111111;
				else			SegVal = ~0b00111111;
				break;
		case 1:	if(common == 1)	SegVal = 0b00000110;
				else			SegVal = ~0b00000110;
				break;
		case 2:	if(common == 1)	SegVal = 0b01011011;
				else			SegVal = ~0b01011011;
				break;
		case 3:	if(common == 1)	SegVal = 0b01001111;
				else			SegVal = ~0b01001111;
				break;
		case 4:	if(common == 1)	SegVal = 0b01100110;
				else			SegVal = ~0b01100110;
				break;
		case 5:	if(common == 1)	SegVal = 0b01101101;
				else			SegVal = ~0b01101101;
				break;
		case 6:	if(common == 1)	SegVal = 0b01111101;
				else			SegVal = ~0b01111101;
				break;
		case 7:	if(common == 1)	SegVal = 0b00000111;
				else			SegVal = ~0b00000111;
				break;
		case 8:	if(common == 1)	SegVal = 0b01111111;
				else			SegVal = ~0b01111111;
				break;
		case 9:	if(common == 1)	SegVal = 0b01101111;
				else			SegVal = ~0b01101111;		
	}		
	return SegVal;
}
 
/*Timer Counter 1 Compare Match A Interrupt Service Routine/Interrupt Handler*/
ISR(TIMER1_COMPA_vect)
{
	seconds++;
 
	if(seconds == 60)
	{
		seconds = 0;
		minutes++;
	}
	if(minutes == 60)
	{
		minutes = 0;
		hours++;		
	}
	if(hours > 23)
		hours = 0;
}

توضیح خط به خط برنامه ساعت دیجیتال با AVR و سون سگمنت:

خط 10:

#define F_CPU	4000000UL

این خط برای مشخص شدن فرکانس کاری میکروکنترلر نوشته شده است و شما باید فیوزبیت های میکروکنترلر را طوری تنظیم کنید تا در 4MHZ کارکند.

خط 11:

#include <avr/delay.h>

افزودن کتابخانه ی delay به برنامه که به وسیله ی دستور

_delay_ms(x)

می توان تاخیر مورد نظر را ایجاد کرد. به جای X زمان مورد نظر را قرار داد.

خط 13:

برای استفاده از وقفه ها در میکروکنترلر های AVR باید این کتابخانه به برنامه اضافه شود.

#include <avr/interrupt.h>

برای اطلاعات بیشتر در مورد این کتابخانه به این لینک مراجعه کنید. توضیحات کاملی هم در مورد سایر کتابخانه های موجود در اتمل استدیو در این سایت است.

خط 15 تا 21:

این خطوط پورت ها و پین های متصل یه سون سگمت را مشخص میکند. به طور مثال:

#define SegDataPort		PORTB

مشخص می کنیم که پایه های a تا g سون سگمنت به پورت B وصل شوند. می توانید با تغییر عبارت PORTB از پورت دلخواه خود استفاده کنید.

خط 25 تا 27:

در این خطوط متغییرهایی که مقدار ساعت دقیقه و ثانیه در آن ها ذخیره می شود تعریف شده است. این متغییر ها به صورت سراسری تعریف شده است. و در همه توابع برنامه شناخته می شوند.

خط 33:

unsigned char DigitTo7SegEncoder(unsigned char digit, unsigned char common);

این خط در واقع معرفی تابع تبدیل اعداد به کد دیجیتال به برنامه است. بدنه تابع بعد از تابع main نوشته شده است.

خط 36:

این خط معرفی تابع روتین وقفه به برنامه است.

خط 41:

int main(void)

شروع تابع اصلی برنامه می باشد.

خط 43:

خروجی کردن پورت های مربوط به پایه های دیتای سون گمنت منظور همان پایه های غیر مشترک.

خط 44:

خروجی کردن پایه های مربوط به پایه های کنترل سون سگمت (پایه های مشترک سون سگمت) و وردی کردن دو پین از پورت برای وصل کردن کلید برای تنظیم ساعت.

خط 47 تا 49:

تنضیمات مربوط به تایمر 1 میکروکنترلر ATmega32 برای ایجاد زمان 1 ثانیه ای

خط 50:

	sei();

توسط این دستور وقفه ی سراسری فعال می شود. تا وقفه سراسری توسط این دستور فعال نشده باشد نمی توان از وقفه ها استفاده کرد.

خط 56 تا 72:

دو دستور if تعریف شده در این خطوط برای تنظیم ساعت و دقیقه کاربرد دارند با هر بار فشرده شدن کلید بک واحد به مقدار ساعت یا دقیقه اضافه می شود ساعت بعد از رسیدن به 23 و دقیقه بعد از رسیدن به 59 صفر می شوند.

خطوط 74 تا 85:

قبل از توضیح عملکرد این خطوط باید عملکرد تابع DigitTo7SegEncoder توضیح داده شود.

عملکرد تابع DigitTo7SegEncoder:

این تابع از خط 104 شروع شده و تا سطر 141 ادامه دارد. نکته ی مهم در مورد این تابع این است که می توانید از این تابع در برنامه ی مختلف خود نیز استفاده کنید. این تابع اعداد ده دهی را به کد سون سگمنت تبدیل می کند. منظور از کد سون سگمنت کدهایی است که می توانید در جدول زیر آن ها را مشاهده کنید.

segment-ascii-table-character-set

این تابع دو ورودی دارد ورودی اول digit نام دارد و عددی است که باید به کد سون سگمنت تبدیل شود. ورودی دوم common نام دارد و نوع پایه مشترک سون سگمنت را مشخص می کند در صورت آند مشترک بودن باید صفر مقدار دهی شود و در کاتد مشترک 1

unsigned char DigitTo7SegEncoder(unsigned char digit, unsigned char common)
{
	unsigned char SegVal;
 
	switch(digit)	
	{	
		case 0:	if(common == 1)	SegVal = 0b00111111;
				else			SegVal = ~0b00111111;
				break;
		case 1:	if(common == 1)	SegVal = 0b00000110;
				else			SegVal = ~0b00000110;
				break;
		case 2:	if(common == 1)	SegVal = 0b01011011;
				else			SegVal = ~0b01011011;
				break;
		case 3:	if(common == 1)	SegVal = 0b01001111;
				else			SegVal = ~0b01001111;
				break;
		case 4:	if(common == 1)	SegVal = 0b01100110;
				else			SegVal = ~0b01100110;
				break;
		case 5:	if(common == 1)	SegVal = 0b01101101;
				else			SegVal = ~0b01101101;
				break;
		case 6:	if(common == 1)	SegVal = 0b01111101;
				else			SegVal = ~0b01111101;
				break;
		case 7:	if(common == 1)	SegVal = 0b00000111;
				else			SegVal = ~0b00000111;
				break;
		case 8:	if(common == 1)	SegVal = 0b01111111;
				else			SegVal = ~0b01111111;
				break;
		case 9:	if(common == 1)	SegVal = 0b01101111;
				else			SegVal = ~0b01101111;		
	}		
	return SegVal;
}

در این تابع از ساختار switch case استفاده شده است. ورودی digit یا case های مختلف مقایسه شده و در صورت برابر بودن کد مربوز به هر کدام توسط دستور return SegVal به خروجی تابع ارسال می شود.

داخل هر case از یک دستور IF استفاده شده تا آند مشترک بودن یا کاتد مشترک بودن مشخص شده و با توجه به این مورد کد مخصوص به هر کدام به درستی ارسال شود.

توضیح خطوط 74 تا 85:

SegDataPort = DigitTo7SegEncoder(seconds%10,1);
SegCntrlPort = ~0x01;
SegDataPort = DigitTo7SegEncoder(seconds/10,1); 
SegCntrlPort = ~0x02;

کدهای مربوط به قسمت ثانیه شرح داده می شود دقیقه و ساعت هم دقیقا مثل همین مورد است.

برای کنترل سون سگمنت از دو پورت segdataport و segcntrlport استفاده شده است. برای نشان دادن یک عدد بر روی سون سگمنت باید دیتای لازم بر روی پایه های a تا g قرار بگیرد علاوه بر این پایه مشترک نیز با توجه به نوع آند مشترک بودن یا کاتد مشترک بودن به منبع تغذیه وصل شود. segdataport  پایه های a تا g را کنترل می کند و segcntrlport  پایه ی مشترک را

برای نشان دادن دو رقم ثانیه از روش زیر استفاده می کنیم به عنوان مثال عدد 23 را بررسی می کنیم برای بدست آوردن یکان عدد 23 از باقی مانده تقسیم آن بر عدد ده استفاده می کنیم. برای بدست آوردن باقی مانده در زبان C می توان از عملگر % استفاده کرد.

SegDataPort = DigitTo7SegEncoder(seconds%10,1);

عبارت seconds%10 عدد 3 را نتیجه می دهد. و تابع DigitTo7SegEncoder کد سون سگمنت آن را تولید می کند برای نمایش این کد برروی سون سگمنت باید پایه مشترک نیز به تغذیه وصل شود که این عمل نیز توسط دستور زیر انجام می شود.

SegCntrlPort = ~0x01;

برای نمایش دهگان عدد کافی است نتیجه تقیم صحیح عدد بر 10 را بدست آوریم.

SegDataPort = DigitTo7SegEncoder(seconds/10,1);

خط 144 تا 160:

در پایان برنامه مربوط به تابع وقفه نوشته شده است که با هر بار وقوع وقفه یک ثانیه به مقدار متغببر ثانیه شمار افزوده می شود. تا به مقدار 60 برسد. و با شصت شدن متغییر ثانبه یک واحد به متغییر دققیه اضافه می شود. ومتغییر ثانیه صفر می شود. نحوه عملکرد متغییر ساعت نیز به همین ترتیب است.

 دانلود فایل های اتمل استدیو

نویسنده: علی عزتی

نوشته های مشابه

7 دیدگاه

  1. با سلام. بایاس مستقیم المان جریان کشی مثل سون سگمنت به صورت مستقیم با میکروکنترلر ایجاد اشکال نمی کند؟

  2. سلام داخل پروتیوس بدون error اجرا میشه .اما نمایش درستی نداره .مشکلش چیه؟

    1. برای تست سون سگمنت باید اون رو در عمل تست کنید نه در نرم افزار!

  3. با سلام کدوم فایل رو باید در آی سی وارد بکنیم البته قبل این که پروگرام بکنیم هر کدوم رو زدم کار نکرد.
    پایه های مشخص شده در نقشه با دیتا شیت سون سگمنت همخوانی نداره میتونید راهنمایی بکنید.
    مثلا پایه ده سگمنت a نیست.
    دیتا شیت اشتباه نوشته یا اینجا اشتباه شده
    سپاس

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا