Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

8-logoПо просьбам трудящихся, было решено продолжить урок по передаче данных через UART. Основной проблемой, на мой взгляд, при общении двух микроконтроллеров является прием данных.

В качестве примера возьмем две Atmega8. Задача первого микроконтроллера переслать массив символов, задача второго принять их и вывести на экран LCD дисплея. Схема будет выглядеть так:

uart821

Код передающего микроконтроллера будет выглядеть так:

#include <mega8.h>
#include <stdio.h>
 
void main(void)
{
 
char massiv[5]={'h','e','l','l','o'};
bit on=0;
int i=0;
 
PORTC=0x01;
DDRC=0x00;
UCSRA=0x00;
UCSRB=0x08;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;
 
while (1)
{
  if(PINC.0==0 && on==0)
  {
    UDR=massiv[i];
    i++;
    if(i>4)
    {
      i=0;
    }
    on=1;
  }
  if(PINC.0!=0)
  {
    on=0;
  }
 
};
}

При нажатии на кнопку передается 1 элемент массива символов, при повторном нажатии — следующий символ и т.д. В результате должен передаться массив «hello». Переменная on нужна для исключения дребезга кнопки (для передачи следующего символа нужно отпустить кнопку и затем нажать).

Второй микроконтроллер принимает данные в прерывании. Код прерывания, CodeWizard создает автоматически. Обработка достаточно большая, пугаться не стоит. Отдельно посмотреть данный код можно выставив галочки как показано на рисунке и щелкнуть File — Program Preview.

uart822

Разберемся с нашим алгоритмом, для нас самое главное это само прерывание:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
 
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
  rx_buffer[rx_wr_index]=data;
  if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
  if (++rx_counter == RX_BUFFER_SIZE)
  {
  rx_counter=0;
  rx_buffer_overflow=1;
  };
};
 
//здесь мы помещаем приходящие данные в массив, заранее известно количество 
//принимаемых символов = 5
uart_data[i]=data;
i++;
if(i>4)
{
  i=0;
}
 
}

Прием производится в прерывании, т.е. как только символ пришел срабатывает прерывание — символ записывается в первый элемент массива, инкрементируется счетчик. В следующее прерывание приходит следующий символ и т.д. Сразу оговорюсь, что количество приходящих символов заранее известно.

Теперь осталось только вывести результат на экран, для этого в цикле выводятся все символы на экран.

1
2
3
4
5
6
7
8
while(j<5) // цикл пока все 5 символов не будут выведены на экран
{
  lcd_gotoxy(j,0); //выбираем место куда будет выводиться символ
  sprintf(lcd_buffer,"%c",uart_data[j]); //преобразовываем символ в понятный для дисплея вид
  lcd_puts(lcd_buffer);  //выводим на экран
  j++;  //увеличить счетчик
}
j=0; // обнулить счетчик

uart823
Схема и прошивка доступны тут

90 комментариев: Урок 8.2. Передача данных через UART в AVR микроконтроллерах. Продолжение

  • (100+10)*1000=110000 это почти в два раза больше чем 65535. Попробуйте написать так.
    С = ((long int)A + (long int)Б) * 1000;

  • Спасибо огромное, попробовал, результат тот же… Проблему решил с другого бока
    C=A*1000+B*100;
    if(A>65)
    {
    D=65000;

    }
    putchar1(‘*’);
    putchar1(A);
    putchar1(B);
    putchar1(‘&’);
    if(PINA.1==0)
    {
    delay_ms(C);

    delay_ms(D);
    PIND.0=1;
    }
    Не очень корректно, но все работает. Просто хотел понять, что же в исходном варианте не так

  • Помоему Вы обманываете нас) Как я и говорил типы нужно приводить, Алексей даже дал вам кусок кода. Все работает.
    debug
    Проблема кроется в функции delay, которая объявлена как:
    void delay_ms(unsigned int n);
    Таким образом в нее больше чем uint16 не запихаешь

  • Здравствуйте! Подскажите, пожалуйста почему при таком цикле :

    while(1)
    {
    if ( UDRE )
    { UDR=’A’; }
    }
    протеус выводит символ ‘A’ беспрерывно , а при таком;

    for (i=0; i<x; i++)
    {
    if ( UDRE )

    { UDR='A'; }
    }
    выводит только последовательно ДВА символа 'A' и останавливается, причем неважно какое "x". И возможно ли как-то перейти на новою строку?

  • Видимо в первом случае по мере отправления флаг то сбрасывается, то устанавливается, но для вас это выглядит как будто он отправляется постоянно. Тут вроде все логично. Почему во втором случае именно так, нужно смотреть по исходнику, но большого смысла заморачиваться не вижу. После каждой отсылки ждите пока флаг отсылки взведется и будет вам счастие

    for (i=0; i < x; i++) { UDR='A'; while ( !(UDRE) ) {} }

    Новая строка символы \r\n

  • Привет.
    Хочю сделать устройство т.е. 3 устройства, скажем на атмега8, которые между собой обменывались кое какими данными, растояние между ними 5-10м. Через UART три устройства на одной линии вроде не пойдёт, а на I2C и SPI может быть растояние большое. Что можете посоветовать?

  • однозначно уарт и rs-485, подробнее не подскажу, пока сам не ковырял

  • Спасибо за подсказку.
    Но лутче было бы сделать на CAN шине с переходником MCP2515+MCP2551, но примеров и библиотек на кодевижие ненашол (есть только для Ардуина) , а я сам только начинающий «чайник» то и на UART будет что делать.

  • подскажите а как передать сразу 5 символов

  • побайтно, один за другим

  • а как сделать передачу даних на компютер например з 10 контролеров?

  • constanta, это у вас контрольная такая? очень просто, передавать все побайтно.

  • нет не контрольная , мне нужно например сделать сбор информации с 10 мест и передать за 1000 метров на комп? как с 10 контроллеров(растояние между контроллерами 50 метров ) собрать инфу и передать за 1000 метров на 1 комп ??

  • 🙂 можно.

  • тут есть много вариантов, поэтому все зависит от исходных данных. очевидно лучше иметь какое то устройство сбора на месте, которое будет опрашивает датчики, а затем передавать, например по ethernet.

  • конешно езернет будет хорошо, так как растояния большое. но вопрос, что ему нужно помочь? написать код для передачи? или составить все оборудивания которое будет опрашивать и передавать даные?

  • код писать ненужно за меня !! мне нужно измерять ток в различних местах на различних обектах і надо з многих мест до 10 мест померять токи и потом за 1000 метров передать ето на комп !!!вот и вопрос как реализовать ?? что нужно з апаратной части и что з програмной??? как по мне юарт неможет работать на такие дистанции. теперь понимаете?? я знаю как ето зделать с помощю техники сименс но ето дорого !
    потому думаю що на атмеге(ардуино) будет дешевле и не хуже!!

  • constanta, никто не знает ваших возможностей и целей, поэтому никто кроме вас не сможет сформулировать условия решения задачи, а решений море. Я вам уже предложил вариант. Хотите тянуть кабель на 1км? Ну тяните, теоретически RS485 может обеспечить до 1200м, проверите так ли это и нам расскажите.

  • ви не поняли меня!! вопрос не в том как считать дани с 10 контроллеров а том как ето обеденить, как засунуть 10 штекеров у комп??

  • это вы не поняли 🙂 вам уже несколько вариантов предложили, вы бы хоть прочитали их. RS485 позволяет подключить несколько устройств на общую шину. Как их опрашивать дело десятое, вы определитесь сначала со схемотехникой.

  • спасибо 🙂

  • admin, добрый вы)

  • вибор сделал в сторону arduiono uno i arduino 5100 ! как думаете хорошо или плохо ??
    или лутче rs485

  • constanta, давно вас небыло.

  • вот много споров на этот счет, что хорошо а что плохо. думаю если задача решается, значит хорошо. лучше или хуже решать вам

  • есть ли перспектива у Atmege или луче взять stm или что другое???

  • Ой, прошу прощения, чё попало написал, всё по перепутал…
    Вот исправленный текст:
    А как принять данные, если количество принимаемых контроллером символов заведомо не известно? Пытаюсь подружить GSM модуль с Atmeg’ой, с отправкой команд с МК проблем нет, модуль их принимает, посылает обратно ответ, а вот как принять эти данные не могу сообразить. Приходит например на модуль СМС с неким текстом, он его шлет в МК, количество букаф, при этом, МК естественно не знает, вот как их принять? И, если можно, небольшой кусочек кода 🙄 Спасибо.

  • если размер не известен, то должен быть спецсимвол окончания строки, или несколько символов.

  • Спецсимвол то есть — ‘\r\n’, т.е. когда передача окончена я знаю, но проблема в другом. Цель такая — вывести присланное содержимое СМС сообщения на php страницу. Ничего в голову не приходит, кроме как создать кучу переменных под каждую букву алфавита и под каждую цифру, потом при по байтном чтении символов из буфера приема, распихивать эти буквы по переменным. Но честно говоря чтото меня смущает создание больше полсотни переменных 😐 Может какой нибудь способ получше бывает? Спасибо.

  • массив?

  • А как реализовать передачу данных по RS485? Очень актуальная тема когда нужно соединить несколько МК и ПК в сеть. В гугле ничего внятно по этой теме не нашел =(

  • вроде хитростей нет, считай микросхема 485 для вас как «удлинитель» в остальном суть такая же, как если бы их не было

  • Я в смысле о modbus-е =) Статья на эту тему (485+modbus) была бы очень востребована.

  • да возможно как нибудь появится

  • Добрый вечер.Подскажите пожалуйста как передать например команду одновременно с трёх кнопок с одного контроллера по UART а с другого принять .Для дистанционного управления .

  • 1 бит = 1 кнопка, запихиваете в 1 байт — отправляете

  • Да так то всё понятно,а как на счет нажатия сразу двух кнопок 2 байта не передадутся нужен какой то алгоритм.Вот в этом то вся и проблема.

  • не внимательно читаете, в байте 8 бит, значит в 1 байт можно затолкать состояние 8 кнопок.

  • ДОБРЫЙ ДЕНЬ.можно затолкать состояние 8 кнопок это понятно, а как например 9 и 10 кнопка это уже 2 байт.Вот в чем проблемка. 🙁

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика