Už chvíli mne štvalo, že nedokážu pro MCU použít takové standardní funkce jako printf. ***/
Po konzultaci s googlem jsem si z prstu vycucal tady toto.
Vím, že existují vymakanější knihovny,
já to však psal pro začátečníky s minimem znalostí MCU.
Musí se však aspoň trochu vyznat v Céčku.
Navrhováno pro MCU ATMEGA16, ATMEGA32, ATMEGA64, …
tedy pro 2 UARTy, ale bez problému to lze předělat.
[code]//**************************************************
// ***** HEADER FILE : UART_routines.h ******
//**************************************************
#ifndef UART_ROUTINES_H
#define UART_ROUTINES_H
#ifndef F_CPU
#define F_CPU 12000000.0 //Zadej správnou frekvenci krystalu (MCU)
#endif
#define UART0_DISABLE UCSR0B = 0x00
#define UART1_DISABLE UCSR1B = 0x00
FILE *u0;
FILE *u1;
int UART0ReadChar(FILE* unused);
int UART1ReadChar(FILE* unused);
int UART0PutChar( char data , FILE* unused);
int UART1PutChar( char data , FILE* unused);
void uart0_init(float);
void uart1_init(float);
#endif
[/code]
[code]//**************************************************
// ***** SOURCE FILE : UART_routines.c ******
//**************************************************
#include <stdio.h>
#include “UART_routines.h”
#include <avr/io.h>
//
/ Inicializace UART0 /
//
void uart0_init(float Baudrate)
{
unsigned int BAUD;
UART0_DISABLE;
UCSR0C = (2<<UMSEL0) | (3 << UCSZ00);
if (Baudrate > 57600.0)
{
UCSR0A = (1<<U2X0);
BAUD = (F_CPU / (8.0 * Baudrate))-0.5;
UBRR0L = BAUD;
UBRR0H = (BAUD >> 8);
}
else
{
UCSR0A = 0x00;
BAUD = (F_CPU / (16.0 * Baudrate))-0.5;
UBRR0L = BAUD;
UBRR0H = (BAUD >> 8);
}
UCSR0B = (1 << RXEN0) | (1 << TXEN0) ;
#if defined( AVR_LIBC_VERSION )
u0 = fdevopen( UART0PutChar, UART0ReadChar );
#else
u0 = fdevopen( UART0PutChar, UART0ReadChar, 0 );
#endif
}
//
/ Inicializace UART1 /
//
void uart1_init(float Baudrate)
{
unsigned int BAUD;
UART1_DISABLE;
UCSR1C = (2<<UMSEL1)|(3<<UCSZ10);
if (Baudrate >= 57600.0)
{
UCSR1A = (1<<U2X1);
BAUD = (F_CPU / (8.0 * Baudrate))-0.5;
UBRR1L = BAUD;
UBRR1H = (BAUD >> 8);
}
else
{
UCSR1A = 0x00;
BAUD = (F_CPU / (16.0 * Baudrate))-0.5;
UBRR1L = BAUD;
UBRR1H = (BAUD >> 8);
}
UCSR1B = (1 << TXEN1) | (1 << RXEN1);
#if defined( AVR_LIBC_VERSION )
u1 = fdevopen( UART1PutChar, UART1ReadChar );
#else
u1 = fdevopen( UART1PutChar, UART1ReadChar, 0 );
#endif
}
//**************************************************
//Function to receive a single byte
//*************************************************
int UART1ReadChar(FILE* unused)
{
unsigned char c;
loop_until_bit_is_set (UCSR1A,RXC1); // Wait untill a char is received
c = UDR1;
int a;
for (a=0;a<100;a++) {}
return c;
}
int UART0ReadChar(FILE* unused)
{
unsigned char c;
loop_until_bit_is_set (UCSR0A,RXC0); // Wait untill a char is received
c = UDR0;
int a;
for (a=0;a<100;a++) {}
return c;
}
//***************************************************
//Function to transmit a single byte
//***************************************************
int UART1PutChar( char data , FILE* unused)
{
loop_until_bit_is_set(UCSR1A, UDRE1);
UDR1 = data;
return 0;
}
int UART0PutChar( char data , FILE* unused)
{
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = data;
return 0;
}
[/code]
/**************************************************************************/
/**************************************************************************/
/*** Už chvíli mne štvalo, že nedokážu pro MCU použít ***/
/*** takové standardní funkce jako printf. ***/
/*** Po konzultaci s googlem jsem si z prstu vycucal ***/
/*** tady toto. ***/
/*** Vím, že existují vymakanější knihovny, ***/
/*** já to však psal pro začátečníky s minimem znalostí MCU. ***/
/*** Musí se však aspoň trochu vyznat v Céčku. ***/
/*** ***/
/*** Navrhováno pro MCU ATMEGA16, ATMEGA32, ATMEGA64, ... ***/
/**************************************************************************/
/**************************************************************************/
#include <avr/io.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include "UART_routines.h"
/**************************************************************************/
/*** Přednadstavení portů ***/
/**************************************************************************/
void static __inline__ port_init(void)
{
PORTA = 0xFF; //na všechny piny pull-up
DDRA = 0x00;
PORTB = 0xFF;
DDRB = 0x00;
PORTC = 0xFF;
DDRC = 0x00;
PORTD = 0xFF;
DDRD = 0x00;
PORTE = 0xFF;
DDRE = 0x00;
PORTF = 0xFF;
DDRF = 0x00;
PORTG = 0xFF;
DDRG = 0x00;
}
/**************************************************************************/
/*** Kompletní inicializace ***/
/**************************************************************************/
void init_devices(void)
{
MCUCR = 0x00;
EIMSK = 0x00;
EICRB = 0x00;
EICRA = 0x00;
TIMSK = 0x00;
port_init();
uart0_init(4800); //Tyto funkce mají poměrně primitivní výpočet
//Před zadáním nějakého numera se v datasheetu
//přesvěčte, zda to procesor vůbec zvládne
uart1_init(115000);
}
/**************************************************************************/
/**************************************************************************/
/*** Tělo programu ***/
/**************************************************************************/
/**************************************************************************/
int main(void)
{
char NMEA[83];
unsigned int Count = 0;
init_devices();
fprintf_P(u1,PSTR("Start programu.\r\n")); //Zaslat hlášku na UART1
while (1) // Do nekonečna
{
fscanf(u0,"%s", NMEA); //Čte string z UART0
fprintf(u1,"%d.....%s\r\n", Count++,NMEA); //a okamžitě ji pošle na UART1
}
}
Šikovnější človíčky jistě napadne, že se to dá překopat a rozšířit pro SPI, TWI atd.