Ach so - o.k. Nun Du mußt entsp. die RS232 - Schnittstelle aktiveren .. wenn Du nur Testdaten in eine Richtung übermitteln willst, reicht es, eine einfache Sendroutine zu definieren ... es gibt auch Biliotheken für C, ich mache sowas aber lieber selber.
Hier die Codeschnippsel ich gehe davon aus, daß Du Dich in C etwas mehr auskennst, auch wenn Du bisher nix mit der seiellen gemacht hast :
Du "nur" InitUart aufrufen, neben sonstigen Initialisierungen.
Code:
Hier meine Uart.h
#ifndef _uart_h_
#define _uart_h_
#define TXRXBUFFERMAX 64
#define SlaveUnitID 80
#define MasterUnitID 110
#ifdef _uart_intern_
// private:
volatile byte UART0_rx_byte_flag = 0;
volatile byte UART0_rx_byte = 0;
volatile byte UART0_transmitting = 0;
byte UART0_rx_a_pos = 0;
byte UART0_rx_array_tmp[TXRXBUFFERMAX + 1];
byte UART0_tx_a_pos = 0;
byte UART0_tx_array_tmp[TXRXBUFFERMAX + 1];
void ClearRX(void);
void ClearRXtmpBuf(void);
void ClearTransmitting(void);
// public:
byte UART0_rx_array[TXRXBUFFERMAX + 1];
byte UART0_tx_array[TXRXBUFFERMAX + 1];
// Prototyping
void UART_Init(void);
byte UART_rx_loop(void);
void ClearRXBuf(void);
void SendUart_tx_array(void);
uint16_t crc(char *str);
byte CheckSlashes(void);
uint16_t crc_xmodem_update (uint16_t crc, const int8_t daten);
#else
// public:
extern byte UART0_rx_array[TXRXBUFFERMAX + 1];
extern byte UART0_tx_array[TXRXBUFFERMAX + 1];
//extern volatile byte UART0_receiving;
extern volatile byte UART0_transmitting;
// Prototyping
extern void UART_Init(void);
extern byte UART_rx_loop(void);
extern void ClearRXBuf(void);
extern void SendUart_tx_array(void);
extern uint16_t crc(char *str);
extern byte CheckSlashes(void);
#endif
#endif
Code:
Hier meine Uart.c
#include <inttypes.h>
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
//-------------------------------------------------------
#include "basdef_h.h"
#include "symtrm_h.h"
//-------------------------------------------------------
#define _uart_intern_
#include "uart.h"
#define UNIT_ID 80
//-------------------------------------------------------
void UART_Init(void)
{
// Init UART 0
// 0 für UART 0
/*
UCSR0A = 0x00; // Control und Status Register
UCSR0B |= (1 << TXEN) | (1 << RXEN) | (1 << TXCIE) | (1 << RXCIE); // TXEN=TX an, RXEN=RX an, RXCIE=RXcomplete Int, TXCIE=TXdto.
UCSR0C |= (1 << USBS0) | (3 << UCSZ0); // asyncron 8N1 -> siehe ATmega128.S.191
UBRR0H = 0;
UBRR0L = 25; // 103 für 9600 || 51 für 19200 || 25 für 38400 - alles bezogen auf 16 MHz
*/
// Ser.Ausgabe => UDR0 = 'a';
// Init UART 1
UCSR1A = 0x00; // Control und Status Register
UCSR1B |= (1 << TXEN) | (1 << RXEN) | (1 << TXCIE) | (1 << RXCIE); // TXEN=TX an, RXEN=RX an, RXCIE=RXcomplete Int, TXCIE=TXdto.
UCSR1C |= (1 << USBS0) | (3 << UCSZ0); // asyncron 8N1 -> siehe ATmega128.S.191
UBRR1H = 0;
UBRR1L = 103; // 103 für 9600 || 51 für 19200 || 25 für 38400 || 16 für 57,6k || 12 für 76,8 || 8 für 115,2 - alles bezogen auf 16 MHz
DDRD |= (1 << DDD5); // DDD5 als Schaltleitung für TX RS485
ClearRX();
ClearRXtmpBuf();
}
//-------------------------------------------------------
void ClearRXtmpBuf(void)
{
memset(UART0_rx_array, 0, TXRXBUFFERMAX + 1);
memset(UART0_rx_array_tmp, 0, TXRXBUFFERMAX + 1);
}
//-------------------------------------------------------
void ClearRXBuf(void)
{
memset(UART0_rx_array, 0, TXRXBUFFERMAX);
}
//-------------------------------------------------------
SIGNAL(SIG_USART1_TRANS) // UART0 TX complete
{
UART0_tx_a_pos++;
if(UART0_tx_a_pos < TXRXBUFFERMAX)
{
if(UART0_tx_array_tmp[UART0_tx_a_pos] == '\0')
{
ClearTransmitting();
}
else // näcshtes zeichen senden
{
UDR1 = UART0_tx_array_tmp[UART0_tx_a_pos];
}
}
else
ClearTransmitting();
}
//-------------------------------------------------------
void ClearTransmitting(void)
{
UART0_transmitting = 0;
UART0_tx_a_pos = 0;
// switch off the RS485-FLAG
PORTD &=~ (1 << DDD5);
}
//-------------------------------------------------------
void SendUart_tx_array(void) // sende gefülltes array, \0 muß diesen beenden !!!
{
while(UART0_transmitting);
UART0_transmitting = 1;
// switch on the RS485-FLAG
PORTD |= (1 << DDD5);
// durch die Übertragung in einen temporären Übertragungspuffer
// ist die nächste Füllung schon möglich
// mit +1 ist ein abschließendes \0 sichergestellt
memset(UART0_tx_array_tmp, 0, TXRXBUFFERMAX + 1);
memcpy(UART0_tx_array_tmp, UART0_tx_array, TXRXBUFFERMAX);
memset(UART0_tx_array, 0, TXRXBUFFERMAX + 1);
UART0_tx_a_pos = 0;
UDR1 = UART0_tx_array_tmp[UART0_tx_a_pos];
}
//-------------------------------------------------------
SIGNAL(SIG_USART1_RECV) // UART0 RX complete
{
UART0_rx_byte_flag = 1;
UART0_rx_byte = UDR1;
// if(!UART0_receiving)
// UART0_receiving = 1;
}
//-------------------------------------------------------
void ClearRX(void)
{
UART0_rx_byte_flag = 0;
UART0_rx_byte = 0;
}
//-------------------------------------------------------
byte UART_rx_loop(void)
{
byte rxok = 0;
byte lastrxb = 0;
if(UART0_rx_byte_flag)
{
// ankommen Zeichen in puffer schreiben
if(UART0_rx_a_pos < TXRXBUFFERMAX)
{
lastrxb = UART0_rx_byte;
UART0_rx_array_tmp[UART0_rx_a_pos] = UART0_rx_byte;
UART0_rx_a_pos++;
UART0_rx_array_tmp[UART0_rx_a_pos] = 0;
}
ClearRX();
}
if((UART0_rx_a_pos >= TXRXBUFFERMAX) || (lastrxb == '>')) // Endezeichen oder Pufferüberschrietung
{
memset(UART0_rx_array, 0, TXRXBUFFERMAX);
memcpy(UART0_rx_array, UART0_rx_array_tmp, UART0_rx_a_pos + 1);
UART0_rx_a_pos = 0;
memset(UART0_rx_array_tmp, 0, TXRXBUFFERMAX);
rxok = 1;
}
return(rxok);
}
Du mußt dann nur einfach ins UART0_tx_array
Code:
Zum Datensenden:
sprintf(UART0_tx_array, "</%03d/%03d/%03d/%03d/%05d/", (int)SlaveUnitID, (int)MasterUnitID, (int)sequenzid, Hold_type, Hold_val);
uint16_t crc_ist = crc(UART0_tx_array);
sprintf(strchr(UART0_tx_array, 0), "%05u/>", crc_ist);
SendUart_tx_array();
In der Hauptschleife von main erfolgt dann noch ein
Code:
if(UART_rx_loop())
{
UART_DATA_Auswertung();
}
mit entsprechender Datenstringauswertung:
void UART_DATA_Auswertung(void)
{
if(UART0_rx_array[0] == '<') // Startzeichen
{
...
}
ClearRXBuf();
}
Ich benütze gerne sprintf - funktionen, wenn es weder Zeit- noch Platzkritisch ist ....
Was auch geht - zum Einseitigen senden:
in main gleich am Anfang:
fdevopen(uart_putchar, NULL, 0); // 4 debugging -> use printf
die Initialsieriung der Baudrate:
Code:
// Init UART 0
UCSRA = 0x00; // Control und Status Register
// UCSRB |= (1 << TXEN) | (1 << RXEN) | (1 << TXCIE) | (1 << RXCIE); // TXEN=TX an, RXEN=RX an, RXCIE=RXcomplete Int, TXCIE=TXdto.
UCSRB |= (1 << RXEN) | (1 << RXCIE); // | (1 << TXEN) | (1 << TXCIE) // TXEN=TX an, RXEN=RX an, RXCIE=RXcomplete Int, TXCIE=TXdto.
UCSRC |= (1 << USBS) | (3 << UCSZ0); // asyncron 8N1 -> siehe ATmega128.S.191
UBRRH = 0;
#define USART_BAUD_RATE 19200
#define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16l)-1)
UBRRL = (unsigned char) USART_BAUD_SELECT;
// UBRRL = 51; // 103 für 9600 || 51 für 19200 || 25 für 38400 || 16 für 57,6k || 12 für 76,8 || 8 für 115,2 - alles bezogen auf 16 MHz
und irgendwo noch ein
Code:
//-------------------------------------------------------
int uart_putchar(char c)
{
if (c == '\n')
uart_putchar('\r');
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}
und dann eben ein printf() .. da ja die Ausgabe an die stdout umgelenkt wird ...
sind alles Codeschnippsel aus funktionierenden Programmen heraus ...
.. ich verwende inzwischen immer die Baudrateninit via dem
#define USART_BAUD_SELECT ....
so muß man weniger Datenblattnachschlagen
Hoff DU kommst damit zurecht und findest Dich rein ..
Liebe Grüße
Vajk
Lesezeichen