Skip to content

Instantly share code, notes, and snippets.

@TorstenC
Created September 3, 2016 21:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TorstenC/7c02b06953d4382648d4ecbc03997076 to your computer and use it in GitHub Desktop.
Save TorstenC/7c02b06953d4382648d4ecbc03997076 to your computer and use it in GitHub Desktop.
Remote Control Receiver for NTF24L01+, SE8R01, RFM70/BK2421, BK2423, XN297 etc.
/* 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