Страница 1 из 1
Atmega IrDA loopback
Добавлено: Ср ноя 02, 2016 11:53:31
Andrejkin
Привет,
Приходится часто иметь дело со связкой TFDU4101+ТOIM4232 (кто не в курсе, это ИК UART приёмо-передатчик и формирователь импульсов)
Перед установкой в устройство желательно удостоверится, что модуль работает. Так как приемопередатчик может ловить свой собственный отраженный сигнал, то алгоритм проверки очень простой - посылаем информацию с атмеги на ТOIM4232 Тх и представляем принятый сигнал простым миганием светодиода. Логически реализуемо, чтобы UART атмеги обрабатывал свои-же закольцованные данные с Тх на Rх?
Как можно доработать на сигнализацию приёма светодиодом код, который раз в некоторый интервал времени посылает на UART"Hello World"?
Код: Выделить всё
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
//Declaration of our functions
void USART_init(void);
unsigned char USART_receive(void);
void USART_send( unsigned char data);
void USART_putstring(char* StringPtr);
char String[]="Hello world!!"; //String[] is in fact an array but when we put the text between the " " symbols the compiler threats it as a String and automatically puts the null termination character in the end of the text
int main(void){
USART_init(); //Call the USART initialization code
while(1){ //Infinite loop
USART_putstring(String); //Pass the string to the USART_putstring function and sends it over the serial
_delay_ms(5000); //Delay for 5 seconds so it will re-send the string every 5 seconds
}
return 0;
}
void USART_init(void){
UBRR0H = (uint8_t)(BAUD_PRESCALLER>>8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
UCSR0C = (3<<UCSZ00);
}
unsigned char USART_receive(void){
while(!(UCSR0A & (1<<RXC0)));
return UDR0;
}
void USART_send( unsigned char data){
while(!(UCSR0A & (1<<UDRE0)));
UDR0 = data;
}
void USART_putstring(char* StringPtr){
while(*StringPtr != 0x00){
USART_send(*StringPtr);
StringPtr++;}
}
Спасибо за подсказки
Андрей
Re: Atmega IrDA loopback
Добавлено: Ср ноя 02, 2016 13:54:14
ARV
делаете обработчик прерывания по приему байта USART, в этом обработчике складываете полученные байты в массив. когда отработает ваша функция USART_putstring(String), в этом массиве должна собраться копия строки - производите сравнение этой строки с содержимым массива и мигаете светодиодом, если совпали. само собой, перед очередной передачей-приемом надо проинициализировать массив и вспомогательные переменные.
Re: Atmega IrDA loopback
Добавлено: Ср ноя 02, 2016 15:07:24
Andrejkin
ARV писал(а):делаете обработчик прерывания по приему байта USART, в этом обработчике складываете полученные байты в массив. когда отработает ваша функция USART_putstring(String), в этом массиве должна собраться копия строки - производите сравнение этой строки с содержимым массива и мигаете светодиодом, если совпали. само собой, перед очередной передачей-приемом надо проинициализировать массив и вспомогательные переменные.
Прерывание должно быть как RXCIE: UART Receive Complete Interrupt Enable ?
Спасибо
Re: Atmega IrDA loopback
Добавлено: Ср ноя 02, 2016 15:31:13
ARV
Andrejkin писал(а):Прерывание должно быть как RXCIE
оно самое
Re: Atmega IrDA loopback
Добавлено: Ср ноя 02, 2016 23:30:01
Andrejkin
Правильно ли написан обработчик прерываний по UART? Функция по сравнению строки и массива Rх будет работать в таком виде?
Код: Выделить всё
#define F_CPU 12000000UL
#include <avr/io.h>
#include <util/delay.h>
#include<avr/interrupt.h>
#include <stdio.h>
#include <string.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
//Declaration of our functions
void USART_init(void);
unsigned char USART_receive(void);
void USART_send( unsigned char data);
void USART_putstring(char* StringPtr);
volatile unsigned char data_in[8] ;
volatile unsigned char data_count;
ISR(USART_RXC_vect)
{
// Get data from the USART in register
data_in [data_count] = UDR;
// End of line!
if (data_in[data_count] == '\n') {
// Reset to 0, ready to go again
data_count = 0;
} else {
data_count++;
}
}
char String[]="Hello"; //String[] is in fact an array but when we put the text between the " " symbols the compiler threats it as a String and automatically puts the null termination character in the end of the text
int main(void){
DDRB = 0xFF;
PORTB = 0x00;
USART_init(); //Call the USART initialization code
sei();
while(1){ //Infinite loop
USART_putstring(String);//Pass the string to the USART_putstring function and sends it over the serial
if (strcmp(data_in, "Hello") == 0)
{
PORTB |= (1 << PB0);
}
else
{
PORTB &= ~(1 << PB0);
}
_delay_ms(1000); //Delay for 1 seconds so it will re-send the string every 1 seconds
}
return 0;
}
void USART_init(void){
UBRRH = (uint8_t)(BAUD_PRESCALLER>>8);
UBRRL = (uint8_t)(BAUD_PRESCALLER);
UCSRB|= (1<<TXEN)|(1<<RXEN)|(1 << RXCIE); // enable receiver and transmitter
UCSRC|= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
}
unsigned char USART_receive(void){
while(!(UCSRA & (1<<RXC)));
return UDR;
}
void USART_send( unsigned char data){
while(!(UCSRA & (1<<UDRE)));
UDR = data;
}
void USART_putstring(char* StringPtr){
while(*StringPtr != 0x00){
USART_send(*StringPtr);
StringPtr++;}
}
Спасибо
Re: Atmega IrDA loopback
Добавлено: Чт ноя 03, 2016 07:31:37
ARV
мне показалось, у вас есть ошибки. возможно, показалось...
1. вы отправляете строку "Hello", а в прерывании проверяете принятый символ на равенство '\n' - в посылаемой строке такого символа нет, и ваш алгоритм не сработает.
2. strcmp может сравнивать строки с нулем на конце, а функция передачи не передает терминальный ноль. да и в прерывании ноль в массив не попадет ни при каких условиях. соответственно, strcmp с большой вероятностью будет всегда сообщать, что строки не равны (если вообще будет что-то сообщать, а не вешать всю программу)
смотрите, что могу предложить вам я
Код: Выделить всё
volatile uint8_t is_ok;
volatile uint8_t ch;
ISR(USART_RXC_vect){
is_ok = (UDR == ch);
}
int main(void){
// инициализация периферии не показана
for(ch=0; ; ch++){
UDR = ch;
_delay_ms(1); // тут задержка должна быть соответствующая скорости USART - больше, чем надо для передачи байта
if(is_ok){
// отображаем успешную приемопередачу
} else {
// отображаем ошибку приемопередачи
}
_delay_ms(50);
}
}
Re: Atmega IrDA loopback
Добавлено: Чт ноя 03, 2016 14:07:31
Andrejkin
Спасибо за подсказки! К сожалению я совсем далек от программирования на Си
Здесь задержка для того, чтобы успеть сравнить, то что приняли с UDR на передачу, перед тем как он опустеет ?
Re: Atmega IrDA loopback
Добавлено: Чт ноя 03, 2016 14:19:13
ARV
задержка нужна, чтобы USART смог передать байт. так как UDR по факту представляет из себя 2 независимых регистра (один на запись для передачи, другой для чтения на приеме), то после того, как UDR "опустеет" при передаче, он немедленно в то же мгновение "наполнится" принятым байтом.
Re: Atmega IrDA loopback
Добавлено: Чт ноя 03, 2016 20:25:28
Andrejkin
Код сейчас такого вида, какие моменты ещё надо подправить? На терминал идут все буквы алфавита подряд;(
Код: Выделить всё
#define F_CPU 12000000UL
#include <avr/io.h>
#include <util/delay.h>
#include<avr/interrupt.h>
#include <stdio.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
//Declaration of our functions
void USART_init(void);
unsigned char USART_receive(void);
void USART_send( unsigned char data);
void USART_putstring(char* StringPtr);
volatile uint8_t is_ok;
volatile uint8_t ch;
ISR(USART_RXC_vect)
{
is_ok = (UDR == ch);
}
char String[]="Hello"; //String[] is in fact an array but when we put the text between the " " symbols the compiler threats it as a String and automatically puts the null termination character in the end of the text
int main(void){
DDRB = 0xFF;
PORTB = 0x00;
USART_init(); //Call the USART initialization code
sei();
while(1){ //Infinite loop
USART_putstring(String); //Pass the string to the USART_putstring function and sends it over the serial
for(ch=0; ; ch++){
UDR = ch;
_delay_ms(1);
if(is_ok){
PORTB |= (1 << PB0);
} else {
PORTB &= ~(1 << PB0);
}
_delay_ms(50);
}
}
return 0;
}
void USART_init(void){
UBRRH = (uint8_t)(BAUD_PRESCALLER>>8);
UBRRL = (uint8_t)(BAUD_PRESCALLER);
UCSRB|= (1<<TXEN)|(1<<RXEN)|(1 << RXCIE); // enable receiver and transmitter
UCSRC|= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
}
unsigned char USART_receive(void){
while(!(UCSRA & (1<<RXC)));
return UDR;
}
void USART_send( unsigned char data){
while(!(UCSRA & (1<<UDRE)));
UDR = data;
}
void USART_putstring(char* StringPtr){
while(*StringPtr != 0x00){
USART_send(*StringPtr);
StringPtr++;}
}