Created
September 3, 2016 21:41
-
-
Save TorstenC/7c02b06953d4382648d4ecbc03997076 to your computer and use it in GitHub Desktop.
Remote Control Receiver for NTF24L01+, SE8R01, RFM70/BK2421, BK2423, XN297 etc.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* RF_24_Remote01.c | |
* Created: 31.08.2016 21:41:47 | |
* Author : Torsten C | |
*/ | |
#define F_CPU 800000UL // 3,3V-CPU läuft an 8MHz-Quarz | |
#include "MyAvrIO.h" // z.B. PORTB, DDRB, SPCR_SPE, uint8_t, … | |
#include <string.h> // z.B. memcpy() | |
#include <stdio.h> // z.B. printf(), benötigt stdout (siehe am Ende) | |
// ToDo: Ausgabe auf Smartphone mit | |
// https://www.mikrocontroller.net/articles/MCURSES | |
/************************************************************************/ | |
/* Header (wird später definiert), ToDo: in *.h auslagern */ | |
/************************************************************************/ | |
void UART_Init(uint32_t UsartBaudrate); | |
enum RF24_Bauds { // der Beken BK2423 kann alle 4 Modi | |
RF24_1Mbps = 0x00, // außer RFM70 = BK2421 | |
RF24_2Mbps = 0x08, // außer RFM70 = BK2421 | |
RF24_250kbps = 0x20, // außer SE8R01 (Massenprodukt) | |
RF24_500kbps = 0x28 // außer NTF24L01+ (Nordic Semiconductor) | |
}; | |
enum RF24_AddrWidths { | |
RF24_3Bytes = 3, // außer SE8R01 | |
RF24_4Bytes = 4, | |
RF24_5Bytes = 5 | |
}; | |
enum RF24_PipeNumbers { | |
RF24_Pipe0 = 0x00, | |
// … nicht genutzt | |
RF24_AllPipesEmpty = 0x07 | |
}; | |
uint8_t RF24_Buffer[33]; // Speicher für RX/TX-Bytes | |
void RF24Init(); | |
void RF24_SetChannel(uint8_t ch); | |
void RF24_SetAddressSingle(uint8_t * Addr, enum RF24_AddrWidths AddrWidth); | |
void RF24_ReadRxPayload(uint8_t MaxLen); | |
void RF24_SetBaud(enum RF24_Bauds Bd); | |
enum RF24_PipeNumbers RF24_RXnotEmpty(); | |
bool RF24_RSSI(); | |
/************************************************************************/ | |
/* Hauptprogramm */ | |
/************************************************************************/ | |
int main(void) { | |
UART_Init(9600); | |
RF24Init(); | |
RF24_SetBaud(RF24_1Mbps); // JD-385 Fernsteuerung | |
RF24_SetChannel(40); // 2440MHz und 2442MHz sind häufig im JD-385-Hopping-Schema | |
RF24_SetAddressSingle( | |
(uint8_t*)"\x66\x88\x68\x68\x68", | |
RF24_5Bytes); // JD-385 Fernsteuerung | |
for(;;) { // Main-Loop, läuft unendlich | |
if (RF24_RXnotEmpty()) { | |
RF24_ReadRxPayload(7); | |
printf("%x-%x-%x-%x-%x-%x", | |
RF24_Buffer[1], RF24_Buffer[2], RF24_Buffer[2], | |
RF24_Buffer[4], RF24_Buffer[5], RF24_Buffer[6]); | |
} | |
} | |
} | |
/************************************************************************/ | |
/* NRF24L01+ (nicht objekt-orientiert, ohne Hardware-Interrupts */ | |
/* ToDo: in *.c auslagern */ | |
/************************************************************************/ | |
/* SPI-Teil */ | |
/************************************************************************/ | |
void SPI_Init() { | |
DDRB |= (1<<3)|(1<<5)|(1<<2); // setze MOSI, SCK und SS als output | |
PORTB |= (1<<2); // setze SS auf high | |
// ToDo: Lib auf mehrere Slaves erweitern | |
SPCR = (SPCR_SPE)|(SPCR_MSTR)|(SPCR_SPR0); // enable master SPI at clock rate Fck/16 | |
// ToDo: Es geht schneller! | |
} | |
uint8_t RF24_Status = 0x0E; // Default: 0x0E = RX FIFO Empty | |
uint8_t * SPI_RxBufferPtr; // Zeiger auf das nächste zu sendende Byte | |
uint8_t SPI_RxBufferLen = 0; // Anzahl der noch zu sendenden Zeichen | |
void SPI_SendSync(uint8_t * bytes, uint8_t len) { | |
SPI_RxBufferLen = len; | |
PORTB &= ~(1<<2); // select slave | |
SPI_RxBufferPtr = (uint8_t*)RF24_Buffer; // Zeiger auf erstes Zeichen merken | |
if (SPSR & SPSR_SPIF) for(;;); // Trap CPU, wenn falsch implementiert | |
// ToDo: LED an | |
while (len) { // Solange SPIMasterBufferLen > 0 | |
SPDR = *bytes++; // Sende Daten und erhöhe Pointer | |
while (SPSR & SPSR_SPIF); // Warte, wenn Byte nicht gesendet wurde | |
*SPI_RxBufferPtr++ = SPDR; | |
len--; // Ein Byte weniger zu senden | |
} | |
RF24_Status = RF24_Buffer[0]; // Das erste Byte ist immer 0x07 = STATUS | |
PORTB |= (1<<2); // setze SS auf high | |
} | |
/************************************************************************/ | |
/* NRF24L01+ Teil */ | |
/************************************************************************/ | |
void RF24_SetChannel(uint8_t ch) { | |
uint8_t bytes[2] = {0x25, ch}; // 0x05|0x20 = RF_CH + W_REGISTER | |
SPI_SendSync(bytes, 2); // In 2 Zeilen mit RF24_Buffer[0] = 0x25; … | |
} | |
void RF24_SetAddressSingle(uint8_t * Addr, enum RF24_AddrWidths AddrWidth) { | |
uint8_t bytes[6] = {0x23, AddrWidth}; // 0x03|0x20 = SETUP_AW + W_REGISTER | |
SPI_SendSync(bytes, 2); | |
bytes[0] = 0x2A; // 0x0A|0x20 = RX_ADDR_P0 + W_REGISTER | |
memcpy(&bytes[1], Addr, AddrWidth); | |
SPI_SendSync(bytes, AddrWidth + 1); | |
} | |
void RF24_SetBaud(enum RF24_Bauds Bd) { | |
uint8_t bytes[2] = {0x26, Bd | 0x06}; // 0x06|0x20 = RF Setup Register + W_REGISTER | |
SPI_SendSync(bytes, 2); // RF_SETUP mit RF-Output = '11' – 0dBm | |
} | |
enum RF24_PipeNumbers RF24_Status_RX_P_NO() { | |
return (RF24_Status & 0x0E) >> 1; | |
}; | |
enum RF24_PipeNumbers RF24_RXnotEmpty() { | |
// uint8_t bytes[2] = {0x17, 0x00}; // 0x17 = FIFO_STATUS | |
// SPI_SendSync(bytes, 2); // Wozu braucht man FIFO_STATUS.RX_EMPTY? | |
// return !(RF24_Buffer[1] & 0x01) // 0x01 = RX_EMPTY | |
RF24_Buffer[0] = 0xFF; // 0xFF = NOP | |
SPI_SendSync(RF24_Buffer, 1); // Liest RF24_Status | |
return RF24_Status_RX_P_NO(); | |
} | |
void RF24_ReadRxPayload(uint8_t MaxLen) { | |
RF24_Buffer[0] = 0b01100001; // '01100001'= R_RX_PAYLOAD | |
SPI_SendSync(RF24_Buffer, MaxLen); // Liest RF24_Status + Payload ab RF24_Buffer[1] | |
} | |
void RF24Init() { | |
SPI_Init(); | |
SPI_SendSync((uint8_t*)"\x21\x00", 2); // EN_AA = 0 (Disable ‘Auto Acknowledgment’ ) | |
SPI_SendSync((uint8_t*)"\x22\x01", 2); // EN_RXADDR = ERX_P0 (Enable RX Addresse/Pipe 0) | |
// überspringe Adressweite Disable Automatic Retransmission | |
SPI_SendSync((uint8_t*)"\x24\x00", 2); // SETUP_RETR = ‘0000’ disabled | |
// überspringe Kanal | |
// überspringe Baud-Rate | |
// überspringe Pipe-Adressen und TX-Adresse | |
SPI_SendSync((uint8_t*)"\x31\x20", 2); // RX_PW_P0 = 32 | |
SPI_SendSync((uint8_t*)"\x20\x02", 2); // CONFIG: EN_CRC = 0, PWR_UP = 1 | |
} | |
/************************************************************************/ | |
/* UART (als stdout für <stdio.h>) */ | |
/* ToDo: in *.c auslagern */ | |
/************************************************************************/ | |
// ToDo: Ring-Puffer und Soft-Real-Time oder Interrupt | |
static int uart_putchar(char u8Data, FILE *stream) { | |
while(!(UCSR0A&(1<<UDRE0))){}; // Warte, falls letztes Byte noch nicht gesendet | |
UDR0 = u8Data; | |
return 0; // zur Kompatibitität mit <stdio.h> | |
} | |
void UART_Init(uint32_t UsartBaudrate) { | |
uint16_t UBRR_Value = (((F_CPU / (UsartBaudrate * 16UL))) - 1); | |
UBRR0H = (uint8_t)(UBRR_Value>>8); | |
UBRR0L = (uint8_t)UBRR_Value; | |
UCSR0C |= UCSR0C_UCSZ01 | UCSR0C_UCSZ00; // Set 8 data bits, no parity, 1 stop bit | |
UCSR0B |= UCSR0B_RXEN0 | UCSR0B_TXEN0; // enable transmission and reception | |
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); | |
stdout = &mystdout; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment