بخش چهارم :
در این بخش می پردازیم به آزمایش کردن اتصال روتاری انکودر شبیه سازی شده و میکروی برنامه ریزی شده (برنامه بخش 2).
آزمایش روتاری انکودر در پروتئوس :
در این برنامه یک میکرویی را انتخاب میکنیم که از امکانات وقفه خارجی و وقفه PIN Change برخوردار باشد . البته منظور این نیست که حتما از این امکانات برخوردار باشه ، بلکه قصد ما از این کار این است که بدانیم از چه راه هایی میتوان این روتاری انکودرها را راه اندازی کرد . میکرویی که ما انتخاب کردیم ATmega48 می باشد . همانطور که قبلا گفته شد ، از دو راه میتوان ولوم هرزگرد را راه اندازی کرد که ما در اینجا از روش وقفه ای استفاده می کنیم ، که این هم خود به دو دسته تقسیم می شود :
1: وقفه های خارجی
2: وقفه PIN Change
برای دوستانی که نمیدونند وقفه PIN Change چی هست یک توضیح مختصر بدم ...
PIN Change یکی از بهترین امکانات میکروهای AVR محسوب میشه . PIN Change در حقیقت یک وقفه پورت است و در آن هر تغییری احساس شد ، برنامه وارد روتین وقفه PIN Change میگردد . حال با توجه به تنظیمات در رجیستر شما میتوانید هر کدام از وقفه یک پورت را فعال کنید و از آن استفاده کنید ... مثلا من میخواهم از پینهای 4 تا 7 پورت D استفاده کنم و در این پینها هر گونه تغییری احساس شد وارد یک زیربرنامه بشوم . برای این کار باید وقفهای مورد نظرم(PIN Change) را در پورت D فعال کنم و برنامه مورد نظرم را در آن روتین بریزم ....
ابتدا همان فایل پروتئوس (نقشه قبلی در بخش 3)را باز کنید و یک save as بسازید و سپس در لیست قطعات، میکروی ATmega48 و Res و Cap را به لیست اضافه کنید.
یک Virtual Terminal بیاورید و آن را به میکرو mega48 متصل کنید .
دو برچسب BIDIR که قبلا آنها را به نام PhaseA و PhaseB نامگذاری کردید را جدا کنید و مدار Debounce را به میکروی 8 اضاف کنید و دو برچسب را به خروجی مدار Debounce وصل کنید و حالا از دو برچسب کپی بگیرید و به INT0 و INT1 وصل کنید . 8 کلید را مطابق شکل نامگذاری کنید .

سپس برنامه ها را وارد کنید و کامپایل کنید ...
استفاده از وقفه های خارجی :
برنامه برای Atmel Studio 6.1 :
کد:
#include <avr/io.h>
#include <avr/iom48.h>
#include <util/delay.h>
#include <avr/interrupt.h>
uint8_t RE=0 , Status , Counter;
void USART_Transmit( uint8_t data )
{
while ( !( UCSR0A & (1<<UDRE0)) );
UDR0 = data;
}
void USART_puts(char *str)
{
uint8_t i=0;
while(str[i])
{
USART_Transmit(str[i]);
i++;
}
}
void USART_put_uint8(uint8_t data)
{
uint8_t a,b=0,c;
c=data;
for(a=0;a<100;a++)
{
if(c==0)break;
c/=10;
if(b==0)b++;
else b*=10;
}
if(b==0)USART_Transmit('0');
for(a=b;a>0;a/=10)
{
c = data/a;
data = data - (c*a);
USART_Transmit(c+48);
}
}
#define Enter \
{\
USART_Transmit(0x0D);\
USART_Transmit(0x0A);\
}
void Rotary_Encoder(uint8_t Input_PhaseA_PhaseB,uint8_t PIN,uint8_t *Var,uint8_t *Status,uint8_t *Counter)
{
uint8_t bit_Right=0 , x ;
x = PIN & Input_PhaseA_PhaseB;
for(uint8_t q = 1;q<200;q <<= 1)
if(Input_PhaseA_PhaseB & q)
{
bit_Right = q;
break;
}
if(x < Input_PhaseA_PhaseB)
{
if(!(x & bit_Right))*Counter += 1;
*Status = x;
}
else if((x == Input_PhaseA_PhaseB) && (*Counter == 2))
{
if (*Status == bit_Right) *Var += 1; // راستگرد
else *Var -= 1; // چپگرد
*Status = 0;
*Counter= 0;
}
else
{
*Status = 0;
*Counter = 0;
}
}
ISR(INT0_vect)
{
Rotary_Encoder(0x0C,PIND,&RE,&Status,&Counter);
}
ISR(INT1_vect)
{
Rotary_Encoder(0x0C,PIND,&RE,&Status,&Counter);
}
int main(void)
{
// USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x33;
// External Interrupt(s) initialization
// INT0: On Mode: Any change
// INT1: On Mode: Any change
EICRA=0x05;
EIMSK=0x03;
EIFR=0x03;
PCICR=0x00;
sei();
uint8_t x=10;
while(1)
{
if(RE!=x)
{
USART_puts("RE=");
USART_put_uint8(RE);
Enter;
x=RE;
}
_delay_ms(50);
}
}
کد:
/*****************************************************
Project : Rotary Encoder
Version : 1.0
Date : 4/19/2014
Author : Saman.Asadi
Chip type : ATmega48
AVR Core Clock frequency: 8.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
#include <stdio.h>
#include <delay.h>
unsigned char RE=0 , Status , Counter;
#define Enter \
{\
putchar(0x0D);\
putchar(0x0A);\
}
void Rotary_Encoder(unsigned char Input_PhaseA_PhaseB,
unsigned char PIN,
unsigned char *Var,
unsigned char *Status,
unsigned char *Counter)
{
unsigned char bit_Right=0 ,x ,q ;
x = PIN & Input_PhaseA_PhaseB;
for(q = 1;q<200;q <<= 1)
if(Input_PhaseA_PhaseB & q)
{
bit_Right = q;
break;
}
if(x < Input_PhaseA_PhaseB)
{
if(!(x & bit_Right))*Counter += 1;
*Status = x;
}
else if((x == Input_PhaseA_PhaseB) && (*Counter == 2))
{
if (*Status == bit_Right)*Var += 1; // راستگرد
else *Var -= 1; // چپگرد
*Status = 0;
*Counter= 0;
}
else
{
*Status = 0;
*Counter = 0;
}
}
interrupt [EXT_INT0] void ext_int0_isr(void)
{
Rotary_Encoder(0x0C,PIND,&RE,&Status,&Counter);
}
interrupt [EXT_INT1] void ext_int1_isr(void)
{
Rotary_Encoder(0x0C,PIND,&RE,&Status,&Counter);
}
void main(void)
{
unsigned char x=10;
CLKPR=0x80;
CLKPR=0x00;
// USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x33;
// External Interrupt(s) initialization
// INT0: On Mode: Any change
// INT1: On Mode: Any change
EICRA=0x05;
EIMSK=0x03;
EIFR=0x03;
PCICR=0x00;
#asm("sei")
while(1)
{
if(RE!=x)
{
printf("RE=%u",RE);
Enter;
x=RE;
}
delay_ms(50);
}
}
حتما" آن را هم وارد کنید و کامپایل کنید .
برنامه شبیه سازی روتاری انکودر برای Atmel Studio :
کد:
#include <avr/io.h>
#include <avr/iom8.h>
#include <util/delay.h>
#define F_CPU 8000000
#define Set_A DDRC |= 1
#define Reset_A DDRC &= 254
#define Set_B DDRC |= 2
#define Reset_B DDRC &= 253
#define Delay _delay_ms(2);
#define Delay_Step _delay_ms(1000);
#define Bounce_Set_A \
{\
Set_A;\
_delay_us(10);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(20);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(30);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(50);\
Reset_A;\
_delay_us(30);\
Set_A;\
_delay_us(30);\
Reset_A;\
_delay_us(20);\
Set_A;\
_delay_us(10);\
Reset_A;\
_delay_us(60);\
Set_A;\
_delay_us(30);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(10);\
Reset_A;\
_delay_us(20);\
Set_A;\
_delay_us(20);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(10);\
}
#define Bounce_Set_B \
{\
Set_B;\
_delay_us(10);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(20);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(30);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(50);\
Reset_B;\
_delay_us(30);\
Set_B;\
_delay_us(30);\
Reset_B;\
_delay_us(20);\
Set_B;\
_delay_us(10);\
Reset_B;\
_delay_us(60);\
Set_B;\
_delay_us(30);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(10);\
Reset_B;\
_delay_us(20);\
Set_B;\
_delay_us(20);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(10);\
}
#define Bounce_Reset_A \
{\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(20);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(30);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(50);\
Reset_A;\
_delay_us(30);\
Set_A;\
_delay_us(30);\
Reset_A;\
_delay_us(20);\
Set_A;\
_delay_us(10);\
Reset_A;\
_delay_us(60);\
Set_A;\
_delay_us(30);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(10);\
Reset_A;\
_delay_us(20);\
Set_A;\
_delay_us(20);\
Reset_A;\
_delay_us(10);\
Set_A;\
_delay_us(10);\
Reset_A;\
_delay_us(10);\
}
#define Bounce_Reset_B \
{\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(20);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(30);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(50);\
Reset_B;\
_delay_us(30);\
Set_B;\
_delay_us(30);\
Reset_B;\
_delay_us(20);\
Set_B;\
_delay_us(10);\
Reset_B;\
_delay_us(60);\
Set_B;\
_delay_us(30);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(10);\
Reset_B;\
_delay_us(20);\
Set_B;\
_delay_us(20);\
Reset_B;\
_delay_us(10);\
Set_B;\
_delay_us(10);\
Reset_B;\
_delay_us(10);\
}
int main(void)
{
PORTB = 0xFF;
while(1)
{
////////////////////////////////////// Bounce is not
if (!(PINB & 1))
{
Set_A;
Delay;
Set_B;
Delay;
Reset_A;
Delay;
Reset_B;
while(!(PINB & 1));
}
if (!(PINB & 2))
{
Set_B;
Delay;
Set_A;
Delay;
Reset_B;
Delay;
Reset_A;
while(!(PINB & 2));
}
if (!(PINB & 4))
{
Set_A;
Delay;
Set_B;
Delay;
Reset_A;
Delay;
Set_B;
Delay;
Set_A;
Delay;
Reset_B;
Delay;
Reset_A;
while(!(PINB & 4));
}
if (!(PINB & 8))
{
Set_B;
Delay;
Set_A;
Delay;
Reset_B;
Delay;
Set_A;
Delay;
Set_B;
Delay;
Reset_A;
Delay;
Reset_B;
while(!(PINB & 8));
}
////////////////////////////////////// by Bounce
if (!(PINB & 16))
{
Bounce_Set_A;
Delay;
Bounce_Set_B;
Delay;
Bounce_Reset_A;
Delay;
Bounce_Reset_B;
while(!(PINB & 16));
}
if (!(PINB & 32))
{
Bounce_Set_B;
Delay;
Bounce_Set_A;
Delay;
Bounce_Reset_B;
Delay;
Bounce_Reset_A;
while(!(PINB & 32));
}
if (!(PINB & 64))
{
Bounce_Set_A;
Delay;
Bounce_Set_B;
Delay;
Bounce_Reset_A;
Delay;
Delay;
Bounce_Set_A;
Delay;
Bounce_Reset_B;
Delay;
Bounce_Reset_A;
while(!(PINB & 64));
}
if (!(PINB & 128))
{
Bounce_Set_B;
Delay;
Bounce_Set_A;
Delay;
Bounce_Reset_B;
Delay;
Delay;
Bounce_Set_B;
Delay;
Bounce_Reset_A;
Delay;
Bounce_Reset_B;
while(!(PINB & 128));
}
}
}
کد:
#include <mega8.h>
#include <delay.h>
#define Set_A DDRC |= 1
#define Reset_A DDRC &= 254
#define Set_B DDRC |= 2
#define Reset_B DDRC &= 253
#define Delay delay_ms(2);
#define Delay_Step delay_ms(1000);
#define Bounce_Set_A \
{\
Set_A;\
delay_us(10);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(20);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(30);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(50);\
Reset_A;\
delay_us(30);\
Set_A;\
delay_us(30);\
Reset_A;\
delay_us(20);\
Set_A;\
delay_us(10);\
Reset_A;\
delay_us(60);\
Set_A;\
delay_us(30);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(10);\
Reset_A;\
delay_us(20);\
Set_A;\
delay_us(20);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(10);\
}
#define Bounce_Set_B \
{\
Set_B;\
delay_us(10);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(20);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(30);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(50);\
Reset_B;\
delay_us(30);\
Set_B;\
delay_us(30);\
Reset_B;\
delay_us(20);\
Set_B;\
delay_us(10);\
Reset_B;\
delay_us(60);\
Set_B;\
delay_us(30);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(10);\
Reset_B;\
delay_us(20);\
Set_B;\
delay_us(20);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(10);\
}
#define Bounce_Reset_A \
{\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(20);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(30);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(50);\
Reset_A;\
delay_us(30);\
Set_A;\
delay_us(30);\
Reset_A;\
delay_us(20);\
Set_A;\
delay_us(10);\
Reset_A;\
delay_us(60);\
Set_A;\
delay_us(30);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(10);\
Reset_A;\
delay_us(20);\
Set_A;\
delay_us(20);\
Reset_A;\
delay_us(10);\
Set_A;\
delay_us(10);\
Reset_A;\
delay_us(10);\
}
#define Bounce_Reset_B \
{\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(20);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(30);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(50);\
Reset_B;\
delay_us(30);\
Set_B;\
delay_us(30);\
Reset_B;\
delay_us(20);\
Set_B;\
delay_us(10);\
Reset_B;\
delay_us(60);\
Set_B;\
delay_us(30);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(10);\
Reset_B;\
delay_us(20);\
Set_B;\
delay_us(20);\
Reset_B;\
delay_us(10);\
Set_B;\
delay_us(10);\
Reset_B;\
delay_us(10);\
}
void main(void)
{
PORTB = 0xFF;
while(1)
{
////////////////////////////////////// Bounce is not
if (!(PINB & 1))
{
Set_A;
Delay;
Set_B;
Delay;
Reset_A;
Delay;
Reset_B;
while(!(PINB & 1));
}
if (!(PINB & 2))
{
Set_B;
Delay;
Set_A;
Delay;
Reset_B;
Delay;
Reset_A;
while(!(PINB & 2));
}
if (!(PINB & 4))
{
Set_A;
Delay;
Set_B;
Delay;
Reset_A;
Delay;
Set_B;
Delay;
Set_A;
Delay;
Reset_B;
Delay;
Reset_A;
while(!(PINB & 4));
}
if (!(PINB & 8))
{
Set_B;
Delay;
Set_A;
Delay;
Reset_B;
Delay;
Set_A;
Delay;
Set_B;
Delay;
Reset_A;
Delay;
Reset_B;
while(!(PINB & 8));
}
////////////////////////////////////// by Bounce
if (!(PINB & 16))
{
Bounce_Set_A;
Delay;
Bounce_Set_B;
Delay;
Bounce_Reset_A;
Delay;
Bounce_Reset_B;
while(!(PINB & 16));
}
if (!(PINB & 32))
{
Bounce_Set_B;
Delay;
Bounce_Set_A;
Delay;
Bounce_Reset_B;
Delay;
Bounce_Reset_A;
while(!(PINB & 32));
}
if (!(PINB & 64))
{
Bounce_Set_A;
Delay;
Bounce_Set_B;
Delay;
Bounce_Reset_A;
Delay;
Delay;
Bounce_Set_A;
Delay;
Bounce_Reset_B;
Delay;
Bounce_Reset_A;
while(!(PINB & 64));
}
if (!(PINB & 128))
{
Bounce_Set_B;
Delay;
Bounce_Set_A;
Delay;
Bounce_Reset_B;
Delay;
Delay;
Bounce_Set_B;
Delay;
Bounce_Reset_A;
Delay;
Bounce_Reset_B;
while(!(PINB & 128));
}
}
}
حالا به میکرو ها آدرس بدید و فرکانس اسیلاتور را روی 8 مگا تنظیم کنید .
چهار کلید بالا مربوط به حالتهای بدون بانس و چهار کلید پایین هم حالتهای مختلف بانس دار می باشد .
برنامه را Play کنید .
و کلید های مورد نظرتان را بزنید .
همانطور که مشاهده می کنید برنامه در مقابل عملکردهای ناقص هیچ گونه عکس العملی نشان نمیدهد ولی در مقابل عملکردهای صحیح عالی کار میکند .


خداییش نگاه کردن این شکل موجها چه حالی میده ... :wow:










یک دیدگاه بنویسید: