Jump to content

    

Нужен учитель

Для обмена по UART правильнее использовать FIFO буфер.

Вот пример под AVR Studio:

/* Файл main.c */
//#define  F_CPU 16000000UL 
#include <avr/io.h>
#include <stdio.h>          // стандартная библиотека ввода/вывод
#include <avr/pgmspace.h>   // утилиты пространства программ
#include "uart.h"

// Создаем поток для ввода/вывода на/с UART для использования стандартных
// функции ввод/вывода
FILE uart_file = FDEV_SETUP_STREAM(uart_put, uart_get, _FDEV_SETUP_RW);

int main (void) 
{
   uart_init(); // название Ф-ции говорит само за себя
   stdout = stdin = &uart_file; // теперь стандартные потоки ссылаются на наш поток

char str[50];

       printf_P(PSTR("Hello, World!\n\r"));
printf_P(PSTR("Input string:"));
scanf_P(PSTR("%49s"),&str);
printf_P(PSTR("%s\n\r"),str);
fprintf(&uart_file, "Bye-bye\n\r"); // Так можно выбирать с каким именно
                                          // потоком работать (для примера)
while (1);
   return 0;
}

 

/* file "uart.h" */
#ifndef UART
#define UART

#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define	UART_FIFO_SIZE	64  // Размер FIFO
#define	UART_BAUD 9600     // Скороть UART

void uart_init(void);		
int uart_get (FILE *stream);	
uint8_t uart_test (void);	
int uart_put (char d, FILE *stream);

#endif /* end UART */

 

/* file "uart.c" */
#include "uart.h"

typedef struct {		// Структура для FIFO
uint8_t	idx_w;		// Указатель на конец очереди FIFO
uint8_t	idx_r;		// Указатель на начало очереди FIFO
uint8_t	count;		// Счетчик количества данных в FIFO
uint8_t buff[uART_FIFO_SIZE]; // Сам FIFO
} FIFO;

static volatile
FIFO txfifo, rxfifo;

/* Initialize UART */

void uart_init()
{
rxfifo.idx_r = 0;	
rxfifo.idx_w = 0;	
rxfifo.count = 0;	
txfifo.idx_r = 0;	
txfifo.idx_w = 0;	
txfifo.count = 0;

UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1; // Настраиваем скорость работы UART
UCSRB = _BV(RXEN)|_BV(RXCIE)|_BV(TXEN);   // Включаем: прием, вызов прерывания по приему, передачу
}

uint8_t uart_test (void)
{
return rxfifo.count;
}

int uart_get (FILE *stream) 	// Ф-ция чтения FIFO для приемника
{
char d;
uint8_t i;

i = rxfifo.idx_r;
while(rxfifo.count == 0); 	// Ожидание входящих данных
d = rxfifo.buff[i++];
cli();
rxfifo.count--;
sei();
if(i >= UART_FIFO_SIZE)
	i = 0;
rxfifo.idx_r = i;
uart_put(d,stream); 		// Эхо ответ
return d;
}

int uart_put (char d, FILE *stream) // Ф-ция записи в FIFO для передатчика
{
uint8_t i;

i = txfifo.idx_w;
while(txfifo.count >= UART_FIFO_SIZE); // ждем когда освободится место в FIFO
txfifo.buff[i++] = d;
cli();
txfifo.count++;
UCSRB |= _BV(UDRIE); // Включаем вызов прерывания по освобождению буфера передатчика
sei();
if(i >= UART_FIFO_SIZE)
	i = 0;
txfifo.idx_w = i;
return 0;
}

ISR(USART_RXC_vect) // Прерывание по приему
{
uint8_t d, n, i;

d = UDR;
n = rxfifo.count;
if(n < UART_FIFO_SIZE) // Если FIFO заполнен данные начнут теряться
{
	rxfifo.count = ++n;
	i = rxfifo.idx_w;
	rxfifo.buff[i++] = d;
	if(i >= UART_FIFO_SIZE)
		i = 0;
	rxfifo.idx_w = i;
}
}

ISR(USART_UDRE_vect) // Прерывание по освобождению буфера передатчика
{
uint8_t n, i;

n = txfifo.count;
if(n) {
	txfifo.count = --n;
	i = txfifo.idx_r;
	UDR = txfifo.buff[i++];
	if(i >= UART_FIFO_SIZE)
		i = 0;
	txfifo.idx_r = i;
}
if(n == 0) // если FIFO пуст,
	UCSRB &= ~_BV(UDRIE); // то выключаем вызов прерывания по освобождению буфера передатчика
}

 

Share this post


Link to post
Share on other sites
Для обмена по UART правильнее использовать FIFO буфер.

Спасибо большое, я обязательно попрактикую это сегодня же, я сам дописал с горем пополам свой код, все работает нормально, даже добавил туда еще функции. Теперь стоит эта штука на борту ВАЗ2107. Заводит ее, открывает закрывает окна, блокирует двери и прочие мелочи. Хоть и мелочи, но приятно. Даже маленький дисплей от нокиа показывает температуру в салоне(датчик тмпературы dht11), потом думаю встроить ее куда нибудь в более важную часть. Пока работы много время нет, но опыт с ней и приходит. Хочу подключить ко всему этому делу gsm sim900 и пару датчиков и сигнализацию получать в виде смс, просто самоучкой быть тяжеловато немного. В принципе как и всегда. Еще раз спасибо за ответ.

Share this post


Link to post
Share on other sites

#include <mega8.h>
#include <delay.h>

int TEMP16;
int T;
unsigned char temp; 
void main(void)

{
DDRB=0x00;  
PORTB=0xFF;
DDRB = 0x00;                                         
DDRD=0xFF;  
PORTD=0x00;
DDRC = 0x00;
PORTC = 0xFF;
ACSR=(1<<ACBG)|(1<<ACIE)|(1<<ACIS1)|(1<<ACIS0)|(1<<ACO);//инициализация компаратора
TEMP16 = 0;

while(1){  // бесконечный цикл
if (PINB.1 == 1 && TEMP16 == 1)
{ // 
     PORTD.3=1;  // включаем 3 пин
     delay_ms(500); // пауза 0.5 секунды
     PORTD.3=0;    // выключаем 3 пин
     TEMP16 = 0;
}     

if (PINB.1 == 0 && TEMP16 == 0)
{ //
PORTD.3=1;  //включаем 3 пин
delay_ms(500); //пауза 0.5 секунды
PORTD.3=0;    //выключаем 3 пин
delay_ms(500); //пауза 0.5 секунды
PORTD.3=1;  // включаем 3 пин
delay_ms(500); //пауза 0.5 секунды
PORTD.3=0;    //выключаем 3 пин
TEMP16 = 1;

}  

if(PINB.2 == 0 && T == 0)
       {

PORTD.2=1;  // включаем второй пин
delay_ms(3000); // пауза 3 секунды
PORTD.2=0;    //выключаем втрой пин
T = 1;

        }

if(PINB.2==1 && T == 1)
   {

    PORTD.2=1;  // включаем второй пин
    delay_ms(3000); //пауза 3 секунды
    PORTD.2=0;    //выключаем втрой пин
    T = 0;
    }


     temp = ACSR;		// читаем ACSR
     temp &= 0x20;		// 5 бит компаратора

if(temp == 0x20)		// если 1
PORTD.1=1;
   else
PORTD.1=0;	// если 0  
   }
}

Здравствуйте! эта штуковина у меня для получения данных о заряде аккумулятора, нескольких "прибамбасов" в виде мигания фарами и звука сирены. вопрос почему эти фнкции выполняются поочередно, если одновременно подать 0 или 1 на оба пина PB1 и PB0, ничего не просходит, а по отдельности работает.

P.S. спасибо за совет с CVavr, им реально удобно пользоватся.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this