Zajmuję się ostatnio projektem, w którym wykorzystuję moduły RFM73 do komunikacji. Jako, że kilka dobrych dni męczyłem się, żeby uruchomić komunikację pomiędzy RPi i STMem zamieszczam działające biblioteki pozwalające na uruchomienie modułu radiowego na tych urządzeniach.
Raspberry Pi
RFM podłączony bezpośrednio do pinów RPi.
| Raspberry Pi | RFM73 |
| GPIO 9 | MISO |
| GPIO 10 | MOSI |
| GPIO 11 | SCK |
| GPIO 24 | CSN |
| GPIO 7 | CE |
| GPIO 25 | IRQ |
Jeśli chcemy podłączyć piny CE, IRQ lub CSN w inny sposób wystarczy zmienić numery portów w pliku rfm73.py
Aby skrypt zadziałał potrzebne nam są biblioteki RPIO oraz SPIdev.
Instalacja RPIO jest bardzo prosta:
sudo apt-get install python-setuptools
sudo easy_install -U RPIO
lub:
git clone https://github.com/metachris/RPIO.git
cd RPIO
sudo python setup.py install
Do działania SPIdev należy posiadać odblokowany sprzętowy moduł SPI. Po wydaniu komendy
lsmod na liście powinniśmy zobaczyć wpis
spi_bcm2708. Jeśli tak nie jest musimy uaktualnić firmware naszej maliny lub odblokować moduł w pliku
/etc/modprobe.d/raspi-blacklsit.conf. Instalacja wygląda następująco:
sudo apt-get update
sudo apt-get install python-dev
mkdir python-spi
cd python-spi
wget https://raw.github.com/doceme/py-spidev/master/setup.py
wget https://raw.github.com/doceme/py-spidev/master/spidev_module.c
sudo python setup.py install
Uruchomienie RFM73 wygląda następująco:
import rfm73
import time
def rfm_interrupt(gpio_id, val):
status = rfm73.register_read(0x07) #read status reg
if status & (1 << 6): #rx data
print "int:", rfm73.receive()
if status & (1 << 4): #max_rt
print "packet not sent"
rfm73.register_write(0x07, status) #clear int flags
rfm73.init(rfm_interrupt)
rfm73.init_banks()
rfm73.receive_mode()
while 1:
time.sleep(0.1)
STM32F303
Całość została uruchomiona na płytce ewaluacyjnej STM32F3Discovery.
| STM32 | RFM73 |
| PB14 | MISO |
| PB15 | MOSI |
| PB13 | SCK |
| PB12 | CSN |
| PB11 | CE |
| PB1 | IRQ |
Uruchomienie modułu:
#include <stm32f30x.h>
#include "rfm73.h"
void clocks_init()
{
//HSE i zegar na 72MHz
RCC->CR = RCC_CR_HSION;
while(!(RCC->CR & RCC_CR_HSIRDY)){};
FLASH->ACR |= FLASH_ACR_LATENCY_0;
RCC->CFGR = (RCC_CFGR_PLLMULL9 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PLLSRC_HSI_Div2);
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY)){};
RCC->CFGR |= RCC_CFGR_SW_PLL;
while(!(RCC->CFGR & RCC_CFGR_SWS_PLL));
RCC->AHBENR |= RCC_AHBENR_GPIOEEN;
GPIOE->MODER |= GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0;
GPIOE->ODR |= GPIO_ODR_8;
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER &= ~GPIO_MODER_MODER1;
//GPIOB->PUPDR |= GPIO_PUPDR_PUPDR1_0;
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR1;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI1_PB;
EXTI->FTSR |= EXTI_FTSR_TR1;
EXTI->IMR |= EXTI_IMR_MR1;
NVIC_EnableIRQ(EXTI1_IRQn);
}
unsigned char length = 0;
unsigned char rx_buf[32];
void EXTI1_IRQHandler(void){
uint8_t status = rfm73_register_read(RFM73_REG_STATUS);
if(status & (1 << 6)) //RX data
{
rfm73_receive(rx_buf, &length);
}
if(status & (1 << 4)) //max_rt
{
//packet not sent
}
rfm73_register_write(RFM73_REG_STATUS, status); //clear ints
EXTI->PR |= EXTI_PR_PR1;
GPIOE->ODR ^= GPIO_ODR_8;
}
int main(void)
{
clocks_init();
rfm73_init();
if(rfm73_is_present())
GPIOE->ODR |= GPIO_ODR_9;
rfm73_mode_transmit();
rfm73_transmit_message("asd",3);
while(1)
{
}
}
Zarówno biblioteka na STM32 jak i na Raspberry Pi wykorzystuje przerwania do obsługi komunikacji przychodzącej. Biblioteki są dostępne na moim
koncie GitHub.