راه اندازی ماژول RFM12 با ATMEGA16 به زبان C و کامپایلر کدویژن

در این نبشته فایلی حاوی یک PDF   آموزشی قرارداده شده که از طرف سایت ایران میکرو (مجله نویز) تهیه شده است و شامل چندین موضوع  می باشد که تنها بخش شروع کار با ماژول RFM12B  آن برای من مد نظر است.در ابتدا می بایست با این ماژول و رجیستر های آن آشنا شد. چنانچه می خواهید با رجیستر های این ماژول  آشنا بشید . این فایل را دانلود کنید.

>> آشنایی با ماژول RFM12B و رجیستر های آن را از اینجا دانلود کنید << 

پس از مطالعه فایلPDF بالا حال به مثالی عملی از این پروژه توسط زبان C  می پردازیم. بنابر این ابتدا به برسی برنامه فرستده می پردازیم :

<< فایل کامل حاوی برنامه RFM12B به زبان C و کامپایلر Codevision با حدف موارد اضافی را از اینجا دانلود کنید > >

برنامه گیرنده شامل یک LCD متصل به پورت A است وتغذیه ماژول  و میکرو را ۵ ولت و اتصالات ماژول همانند زیر متصل نمایید.

سوالات را همواره با شماره ۰۹۱۳۷۸۷۵۴۹۱ مطرح نمایید.

//ATMEGA16 SIDE | RF12 SIDE
// SCK—————->SCK
// MISO—————>SDO
// MOSI—————>SDI
// SS—————–>nSEL

چند خط بالا نشان دهنده نحوه اتصال پین های میکرو و ماژول به یکدیگرند.ولتاژ ماژول و میکرو  ۵ ولت می باشد.

#include <mega16.h>
#include <stdlib.h>
#include <stdio.h>
#include <delay.h>

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

#define DDR_IN 0
#define DDR_OUT 1

#define PORT_SEL PORTB
#define PIN_SEL PINB
#define DDR_SEL DDRB

#define PORT_SDI PORTB
#define PIN_SDI PINB
#define DDR_SDI DDRB

#define PORT_SCK PORTB
#define PIN_SCK PINB
#define DDR_SCK DDRB

#define PORT_SDO PORTB
#define PIN_SDO PINB
#define DDR_SDO DDRB

#define PORT_IRQ PORTD
#define PIN_IRQ PIND
#define DDR_IRQ DDRD

#define PORT_DATA PORTD
#define PIN_DATA PIND
#define DDR_DATA DDRD

#define PB7 3//–\
#define PB6 2// |
#define RFXX_SCK 7// |
#define RFXX_SDO 6// |RF_PORT
#define RFXX_SDI 5// |
#define RFXX_SEL 4// |
#define NC 1// |
#define PB0 0//–/

#define SEL_OUTPUT() DDR_SEL |= (1<<RFXX_SEL)
#define HI_SEL() PORT_SEL|= (1<<RFXX_SEL)
#define LOW_SEL() PORT_SEL&=~(1<<RFXX_SEL)

#define SDI_OUTPUT() DDR_SDI |= (1<<RFXX_SDI)
#define HI_SDI() PORT_SDI|= (1<<RFXX_SDI)
#define LOW_SDI() PORT_SDI&=~(1<<RFXX_SDI)

#define SDO_INPUT() DDR_SDO&= ~(1<<RFXX_SDO)
#define LOW_SDO() PORT_SDO&= (1<<RFXX_SDO)
#define SDO_HI() PIN_SDO&(1<<RFXX_SDO)

#define SCK_OUTPUT() DDR_SCK |= (1<<RFXX_SCK)
#define HI_SCK() PORT_SCK|= (1<<RFXX_SCK)
#define LOW_SCK() PORT_SCK&=~(1<<RFXX_SCK)

#define RF12_IRQ 2
#define IRQ_IN() DDR_IRQ &=~(1<<RF12_IRQ)
#define WAIT_IRQ_LOW() while(PIND&(1<<RF12_IRQ))

#define RF12_DATA 4//PD4
#define DATA_OUT() DDR_DATA|=1<<RF12_DATA
#define HI_DATA() PORT_DATA|=1<<RF12_DATA

#define RFM12_Reset PORTB.0
#define ON 0
#define OFF 1

در قسمت های  بالا نامگذاری هایی برای پرتها و … شده است که چند تایی از آنها در این پروژه کاربردی ندارند و با حذف آنها هیچ مشکلی در اجرای برنامه پیش نمی آید.

void RFsend_PORT_INIT(void)
{
HI_SEL();
HI_SDI();
LOW_SCK();
SEL_OUTPUT();
SDI_OUTPUT();
SDO_INPUT();
SCK_OUTPUT();
}

تابع بالا کار پیکر بندی برای پورت های میکرو رو انجام می دهد.

unsigned int RFsend_WRT_CMD(unsigned int aCmd)
{
unsigned char i;
unsigned int temp=0;
LOW_SCK();
LOW_SEL();
for(i=0;i<16;i++)
{
temp<<=1;
if(SDO_HI())
{
temp|=0x0001;
}
LOW_SCK();
if(aCmd&0x8000)
{
HI_SDI();
}
else
{
LOW_SDI();
}
HI_SCK();
aCmd<<=1;
};
LOW_SCK();
HI_SEL();
return(temp);
}

تابع بالا شبیه ساز پروتکل SPI در میکرو می باشد که توسط برنامه نویسی شبیه سازی شده است با این تفاوت که در SPIمیکرو ارتباط ۸ بیتی است در صورتی که در این برنامه ارتباط ۱۶ بیتی است.در نبشته های قبلی ارتباط توسط جادوگر کدویزارد توضیح داده شده است که ۸ بیتی است.در حقیقت این برنامه یک ارتباط SPI شانزده بیتی می باشد.

void RF12send_INIT(void)
{
RFsend_WRT_CMD(0x80E7);//EL,EF,433band,12.0pF
RFsend_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
RFsend_WRT_CMD(0xC602);//A140=430.8MHz
RFsend_WRT_CMD(0xC647);//19.2kbps
RFsend_WRT_CMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
RFsend_WRT_CMD(0xC2AC);//AL,!ml,DIG,DQD4
RFsend_WRT_CMD(0xCA81);//FIFO8,SYNC,!ff,DR
RFsend_WRT_CMD(0xCA83);//@PWR,NO RSTRIC,!st,!fi,OE,EN
RFsend_WRT_CMD(0x9850);//!mp,9810=30kHz,MAX OUT
RFsend_WRT_CMD(0xE000);//NOT USE
RFsend_WRT_CMD(0xC800);//NOT USE
RFsend_WRT_CMD(0xC040);//1.66MHz,2.2V
}

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

>> آشنایی با ماژول RFM12B و رجیستر های آن را از اینجا دانلود کنید دانلود کنید<< 

این قسمت از برنامه مقدار رجیستر های برنامه را تنظیم می کند.جابجایی خط به خط آنها هیچ اشکالی ندارد زیرا گاها ۸ بیت ابتدایی انها ثابت و بعنوان آدرس رجیستر می باشد.تنها نکته مهم این است که تنظیمات فرستنده و گیرنده به غیر از قسمت فرستندگی و گیرندگی نباید غیره یکسان باشند.برای آشنایی با کار تابع RFsend_WRT_CMD به قسمت های پایین مراجعه نمایید.

void RF12_SEND(unsigned char aByte)
{
//while(PIND&(1<<2));//wait for previously TX over
RFsend_WRT_CMD(0xB800+aByte);
LOW_SEL(); //Reset Rfm12_cs
while(PINB.6!=1);//Bitwait Rfm12_sdo , Set
}

این تابع دیتا را ارسال می کند.

void DataSend(unsigned char Device)
{
RFsend_PORT_INIT();
RF12send_INIT();
DDRD|=(1<<RF12_DATA);
PORTD|=(1<<RF12_DATA);// SET nFFS pin HI when using TX register
DDRD&=~(1<<2); //PD2(INT0)
RFsend_WRT_CMD(0x0000);//read status register
RFsend_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
RF12_SEND(0xAA);//PREAMBLE
RF12_SEND(0xAA);//PREAMBLE
RF12_SEND(0xAA);//PREAMBLE
RF12_SEND(0x2D);//SYNC HI BYTE
RF12_SEND(0xD4);//SYNC LOW BYTE
RF12_SEND(Device);
RF12_SEND(0xAA);//DUMMY BYTE
RF12_SEND(0xAA);//DUMMY BYTE
RF12_SEND(0xAA);//DUMMY BYTE
RFsend_WRT_CMD(0x8201);
}

تابع بالا وظیفه ارسال تنظیمات ماژول را بر عهدا دارد که مقادیر تنظیمات بدست آمده برای ماژول توسط ای تابع ارسال میکنیم.

unsigned char i;
void main(void)
{
// Global enable interrupts
#asm(“cli”);
// Input/Output Ports initialization
// Port B initialization
DDRB.0=0;//Reset PIN For RFM12B
PORTB.0=1;//0 For Reset
DDRB.4=1;
DDRB.5=0;
DDRB.6=1;
DDRD.7=1;

// Port C initialization
PORTC=0x00;
DDRC=0x00;
// Port D initialization

PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
while(1)
{
DataSend(i);
i++;
delay_ms(500);
};
}

قسمت بالا عدد i را ارسال و سپس یک واحد به آن اضافه می کند.به یاد داشته باشید RFM12 دارای ارتباط ۱۶ بیتی است و لی دادهای ۸ بیتی را ارسال می کند.

قسمت گیرنده:

//ATMEGA16 SIDE | RF12 SIDE
// SCK—————->SCK
// MISO—————>SDO
// MOSI—————>SDI
// SS—————–>nSEL

#include <mega16.h>
#include <stdlib.h>
#include <stdio.h>
#include <delay.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x1B ;PORTA
#endasm
#include <lcd.h>

#define DDR_IN 0
#define DDR_OUT 1

#define PORT_SEL PORTB
#define PIN_SEL PINB
#define DDR_SEL DDRB

#define PORT_SDI PORTB
#define PIN_SDI PINB
#define DDR_SDI DDRB

#define PORT_SCK PORTB
#define PIN_SCK PINB
#define DDR_SCK DDRB

#define PORT_SDO PORTB
#define PIN_SDO PINB
#define DDR_SDO DDRB

#define PORT_IRQ PORTD
#define PIN_IRQ PIND
#define DDR_IRQ DDRD

#define PORT_DATA PORTD
#define PIN_DATA PIND
#define DDR_DATA DDRD

#define PB7 3//–\
#define PB6 2// |
#define RFXX_SCK 7// |
#define RFXX_SDO 6// |RF_PORT
#define RFXX_SDI 5// |
#define RFXX_SEL 4// |
#define NC 1// |
#define PB0 0//–/

#define SEL_OUTPUT() DDR_SEL |= (1<<RFXX_SEL)
#define HI_SEL() PORT_SEL|= (1<<RFXX_SEL)
#define LOW_SEL() PORT_SEL&=~(1<<RFXX_SEL)

#define SDI_OUTPUT() DDR_SDI |= (1<<RFXX_SDI)
#define HI_SDI() PORT_SDI|= (1<<RFXX_SDI)
#define LOW_SDI() PORT_SDI&=~(1<<RFXX_SDI)

#define SDO_INPUT() DDR_SDO&= ~(1<<RFXX_SDO)
#define LOW_SDO() PORT_SDO&= (1<<RFXX_SDO)
#define SDO_HI() PIN_SDO&(1<<RFXX_SDO)

#define SCK_OUTPUT() DDR_SCK |= (1<<RFXX_SCK)
#define HI_SCK() PORT_SCK|= (1<<RFXX_SCK)
#define LOW_SCK() PORT_SCK&=~(1<<RFXX_SCK)

#define RF12_IRQ 2
#define IRQ_IN() DDR_IRQ &=~(1<<RF12_IRQ)
#define WAIT_IRQ_LOW() while(PIND&(1<<RF12_IRQ))

#define RF12_DATA 4//PD4
#define DATA_OUT() DDR_DATA|=1<<RF12_DATA
#define HI_DATA() PORT_DATA|=1<<RF12_DATA

#define RFM12_Reset PORTB.0
#define ON 0
#define OFF 1

void RFrecieve_PORT_INIT(void)
{
HI_SEL();
HI_SDI();
LOW_SCK();
//SET nFFS pin HI when using FIFO
HI_DATA();
SEL_OUTPUT();
SDI_OUTPUT();
SDO_INPUT();
SCK_OUTPUT();
IRQ_IN();
DATA_OUT();
}

unsigned int RFrecieve_WRT_CMD(unsigned int aCmd)
{
unsigned char i;
unsigned int temp;
temp=0;
LOW_SCK();
LOW_SEL();
for(i=0;i<16;i++)
{
if(aCmd&0x8000)
{
HI_SDI();
}
else
{
LOW_SDI();
}
HI_SCK();
temp<<=1;
if(SDO_HI())
{
temp|=0x0001;
}
LOW_SCK();

aCmd<<=1;
};
HI_SEL();
return(temp);
}

void RF12recieve_INIT(void)
{
RFrecieve_WRT_CMD(0x80E7);//EL,EF,433band,11.5pF
RFrecieve_WRT_CMD(0x82D9);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
RFrecieve_WRT_CMD(0xC602);//434MHz
RFrecieve_WRT_CMD(0xC647);//4.8kbps
RFrecieve_WRT_CMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
RFrecieve_WRT_CMD(0xC2AC);//AL,!ml,DIG,DQD4
RFrecieve_WRT_CMD(0xCA81);//FIFO8,SYNC,!ff,DR
RFrecieve_WRT_CMD(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN
RFrecieve_WRT_CMD(0x9850);//!mp,9810=30kHz,MAX OUT
RFrecieve_WRT_CMD(0xE000);//NOT USE
RFrecieve_WRT_CMD(0xC800);//NOT USE
RFrecieve_WRT_CMD(0xC040);//1.66MHz,2.2V
}

unsigned char RF12_RECV(void)
{
unsigned int FIFO_data;
//WAIT_IRQ_LOW();
LOW_SEL(); //Reset Rfm12_cs
while(PINB.6!=1);//Bitwait Rfm12_sdo , Set
//RFrecieve_WRT_CMD(0x0000);
FIFO_data=RFrecieve_WRT_CMD(0xB000);
return(FIFO_data&0x00FF);
}

unsigned char uChRecieve=0;
unsigned char DataRecieve(void)
{
//Initialize command port
RFrecieve_PORT_INIT();
//Initialize RF12 chip
RF12recieve_INIT();
//Init FIFO
RFrecieve_WRT_CMD(0x82D9);
//Enable FIFO
RFrecieve_WRT_CMD(0xCA81);
//Disable FIFO
RFrecieve_WRT_CMD(0xCA83);
uChRecieve=RF12_RECV();
return(uChRecieve);
}

unsigned char lcd_buff[10];
void main(void)
{
// Input/Output Ports initialization
// Port B initialization
DDRB.0=0;//Reset PIN For RFM12B
PORTB.0=1;//0 For Reset
DDRB.4=1;
DDRB.5=0;
DDRB.6=1;
DDRD.7=1;

// Port C initialization
PORTC=0x00;
DDRC=0x00;
// Port D initialization

PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

lcd_init(16);
lcd_clear();
lcd_putsf(“Ready”);
delay_ms(100);

while(1)
{
uChRecieve=DataRecieve();
sprintf(lcd_buff,”%d”,uChRecieve);
lcd_clear();
lcd_puts(lcd_buff);
};
}

محصولات رادیویی ما:(ریموت و گیرنده های برد کوتاه و بلند لرنینگ و کد فیکس)

One Comment on “راه اندازی ماژول RFM12 با ATMEGA16 به زبان C و کامپایلر کدویژن”

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

نشانی ایمیل شما منتشر نخواهد شد.