Ok, most of the work done. at least, I've thought.
I want two computer to communicate serially over RF (using the TRW-24g).
I've built a PCB that uses Atmega88 which connect through max3232 to RS232 (for USART) on one hand and to the TRW-24g on the other (using SPI).
The USART working great.
I'm NOT using external clock. (will it affect only the USART, of the SPI too?)
I'm working for the serial with baud rate 4800.
the UBRR is 12.
I've set the F_CPU to 8E6.
what are all those speeds?
what does the speed (16Mhz on Lars's example) do?
What does it has to do with the clock speed (8Mhz)?
Can you please help me to understand all the speeds/baud rates.
You can assume, that I've built the PCB right, and all the MASKs/PORTs fits.
This is my code:
Code: Select all
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Lars Jonsson (User name Lajon at www.avrfreaks.net) wrote this file.
* As long as you retain this notice you can do whatever you want with this
* stuff. If we meet some day, and you think this stuff is worth it, you can
* buy me a beer in return. Lars Jonsson
* ----------------------------------------------------------------------------
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include "config.h"
#include <avr/delay.h>
#include "trf24g_config.h"
#include "trf24g.h"
#define TRF24G_START_CONFIG() TRF24G_CSCE_PORT |= TRF24G_CS_MASK; _delay_us(5)
#define TRF24G_END_CONFIG() TRF24G_CSCE_PORT &= (uint8_t)~TRF24G_CS_MASK;
#define TRF24G_ACTIVE() TRF24G_CSCE_PORT |= TRF24G_CE_MASK; _delay_us(5)
#define TRF24G_INACTIVE() TRF24G_CSCE_PORT &= ~TRF24G_CE_MASK;
static uint8_t trf24gConfig[15] = {
/* 0 */ TRF24G_PAYLOAD_SIZE * 8, // DATA2_W
/* 1 */ TRF24G_PAYLOAD_SIZE * 8, // DATA1_W
/* 2 */ 0,0,0,0,0, // ADDR2 not used
/* 7 */ TRF24G_ADDR1, // ADDR1
/* 12 */ ((TRF24G_ADDR_SIZE * 8) << 2) |
((TRF24G_CRC_SIZE == 0) ? 0b00 : ((TRF24G_CRC_SIZE == 1) ? 0b01 : 0b11)),
/* 13 */ (0 << 7) | // RX2 active or not (not for now)
(1 << 6) | // Shockburst (always)
(TRF24G_1MBPS << 5) | // Speed
(0b011 << 2) | // 16MHz always
0b11, // Full power always
/* 14 */ (TRF24G_CHANNEL << 1) | TRF24G_RX
};
#define ADDR1 7
static inline uint8_t spiSend(uint8_t d)
{
SPDR = d;
while(!(SPSR & (1<<SPIF)))
;
return SPDR;
}
void trf24gInit(void)
{
uint8_t i;
// DDR for trf24g control, CS and CE are outputs
TRF24G_CSCE_DDR |= TRF24G_CS_MASK|TRF24G_CE_MASK; //@tal
// DDR for SPI, MOSI and SCK are outputs
TRF24G_SPI_DDR |= TRF24G_SPI_MOSI_MASK|TRF24G_SPI_SCK_MASK;
TRF24G_SPI_SS_PORT |= TRF24G_SPI_SS_MASK; //drive SS high //@tal
// SPI master, trailing edge setup
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); // /8 clock (8Mhz/8 = 1Mhz)
SPSR |= (1<<SPI2X);
//SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0); // /4 clock (works also)
_delay_ms(3);
// >3ms startup
TRF24G_START_CONFIG();
for(i = 0; i < sizeof(trf24gConfig); i++) { //send the configuration word to the SPI
spiSend(trf24gConfig[i]);
}
TRF24G_END_CONFIG();
#if TRF24G_RX
TRF24G_ACTIVE();
#endif
}
void trf24gReconfigure(uint8_t channel, bool rx)
{
uint8_t cfg = channel << 1;
cfg |= rx;
TRF24G_INACTIVE();
TRF24G_START_CONFIG();
spiSend(cfg);
TRF24G_END_CONFIG();
if (rx) {
TRF24G_ACTIVE();
}
}
bool trf24gReceive(void *p)
{
uint8_t dr = TRF24G_DR1_PIN & TRF24G_DR1_MASK;
if (dr) {
uint8_t n = TRF24G_PAYLOAD_SIZE;
uint8_t *buf = (uint8_t*)p;
do {
*buf++ = spiSend(0);
} while(--n);
}
return dr;
}
void trf24gSend(void *p)
{
uint8_t n = TRF24G_ADDR_SIZE;
uint8_t *buf = (uint8_t*)p;
uint8_t *a = trf24gConfig + ADDR1 + 5 - TRF24G_ADDR_SIZE;
TRF24G_ACTIVE();
do {
spiSend(*a++);
} while(--n);
n = TRF24G_PAYLOAD_SIZE;
do {
spiSend(*buf++);
} while(--n);
TRF24G_INACTIVE();
}
//#####################################################################
//####################### USART #######################
//#####################################################################
void usart_putc(unsigned int input) {
// wait until UDR ready
while(!(UCSR0A & (1 << UDRE0)));
UDR0 = input; // send USART
}
void setBoudRateByMethod()
{
UBRR0H = 0;
UBRR0L = 12;
}
void usart_init()
{
// init the USART (Universal Sync and ASync Receiver and Transmiter) bits
// there 3 groups of control status bits (UVSR[A-C])
UCSR0A = (1<<RXC0); // clear the Receive Bit
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); // enable Receive Rx;enable Transmit Tx;Enable Rx Interrupt
UCSR0C = (3<<UCSZ00) | (1<<UMSEL01) | (1<<USBS0); // 8 dataBits, No parity, and 2 stopBits
setBoudRateByMethod();
}
SIGNAL(SIG_USART_RECV)
{
unsigned int input;
while (!(UCSR0A & (1 << RXC0)));
input=UDR0; // read an int from the serial port
PORTC |= (1 << PC4); //@TODO - remove, just for debug
char buffer[TRF24G_PAYLOAD_SIZE];
buffer[0] = input;
trf24gSend(buffer);
_delay_ms((TRF24G_TIME_ON_AIR + 999) / 1000); /* round up to ms */
usart_putc(input + 1); // for debug, the sender will return it to the terminal
}
//#####################################################################
//####################### main #######################
//#####################################################################
int main(void)
{
trf24gInit();
usart_init(); // init USART
PORTC &= (0 << PC5); //@TODO - remove, just for debug
PORTC &= (0 << PC4); //@TODO - remove, just for debug
// ####################
// #### The SENDER ####
// ####################
if (TRF24G_RX == 0)
{
PORTC |= (1 << PC5); //@TODO - remove, just for debug
sei(); // enable interrupts
while(1)
{
}
} else
// ######################
// #### The RECEIVER ####
// ######################
{
PORTC |= (1 << PC4); //@TODO - remove, just for debug
while(1)
{
char buffer[TRF24G_PAYLOAD_SIZE];
if (trf24gReceive(buffer))
{
usart_putc(buffer);
}
}
}
return(0);
}