Курс AVR123.nm.ru


Electronic Banner Exchange (ElBE)
 


Консультации  по электронике и электронным компонентам  по ICQ 397877008
 

Краткий курс - Самоучитель - AVR - быстрый старт с нуля



Советую читать курс с начала !


Как устроен микроконтроллер AVR

Все задачи-упражнения курса

Язык Си для микроконтроллеров

 

Задача - упражнение   5

 

Цель задачи: 

1)  Создать программу для  микроконтроллера ATmega16 принимающую и передающую данные по интерфейсу rs232  с помощью USART встроенного в AVR ATmega  на COM-порт ПК.

Схемы и компоненты для сопряжения МК с COM-портом ПК, так же программы для управления и лога данных смотрите  в задаче 4

2)  Закрепить навыки создания программы  в CVAVR с помошью мастера начального кода и продолжить учится   использовать язык Си для микроконтроллеров


3)  Научиться подключать и управлять символьным ЖКИ - LCD 16x2 (c  контроллером  hd44780) - они очень популярны ! 

LCD бывают от 1 до 4 строк длиной до 40-ка символов.
Смотрите каталог электронных компонентов.

 

 

 

поиск   GOOGLE   по 
Краткому Курсу AVR

Подставьте слово
и получите результат

 


Книги и учебники по электронике и микроконтроллерам AVR PIC ARM  скачать в библиотеке.

 

Как и чем прошить МК AVR 
читайте на
странице 7 курса !

 

Подробно и с картинками симуляция программы
в VMLAB рассмотрена в задаче 3


АЦП  ATmega16 в  задаче 9

 

 

 

Для выполнения задачи необходимы :

- Установленный компилятор CodeVisionAVR

- Установленный эмулятор VMLAB  - Visual Micro Lab

- Data Sheet
  - ДШ на МК AVR ATmega16

- Знать ХОРОШО теоретический материал курса - до стр. 6

- Выполнить предыдущие задчачи-упражнения 

 

Это нужно не мне - это нужно ВАМ !

 

 

 

Делаем :

Для того чтобы МК мог обмениваться данными с компьютером (ПК) или другим терминальным устройством - т.е.  принимать и отправлять данные  (обычно это байты, т.е. 8-ми битные числа) 

нужно : 

1) соединить его физически с ПК по схемам и способами
     описанными в задаче 4 или с симулятором    
 

2) настроить == сконфигурировать USART  МК   

- установить скорость передачи данных в бодах такую же как на ПК
  (из перечня скоростей стандартных для ПК) или как в
  симуляторе   с погрешностью до 1%       


- установить формат передачи данных как на подключаемом
            устройстве - это ПК, терминал или симулятор.

- включить прием и/или передачу данных - это можно делать
  по мере необходимости в программе.

 

Стандартные скорости обмена вашего ПК можно посмотреть через 
"панель управления" -> "система" -> "COM-порт" -> "свойства"

 

     
 

Для обеспечения с достаточной точностью скорости обмена обычно требуются кварцы специальных UART'овских частот - их можно найти в таблице ДШ в разделе USART. 

Не советую использовать внешний или встроенный RC-генератор для тактирования МК при обмене с ПК - их точность слишком мала и наверняка будут сплошные ошибки в передаче. 

Мастер настройки USART МК в  CVAVR (картинка ниже!) подсвечивает недопустимо большую ошибку в скорости
передачи КРАСНЫМ цветом !

 
     

 

Реклама недорогих радиодеталей почтой:

 

 

Пример настройки и включения USART ATmega16 
на прием и передачу для любого компилятора Си 

 

     
 

// USART initialization
// Communication Parameters: 8 Data, No Parity, 1 Stop  8N1
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous

UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x86;

// USART Baud rate: 115200  для кварца 11,059 МГц
UBRRH=0x00;
UBRRL=0x05;

 
     

 

Обязательно! Найдите в ДШ все использованные регистры   
и посмотрите что мы в них записали и зачем. 

Вы должны знать значение каждого бита! 

Не ленитесь !

 


Формат передачи данных (см. ДШ Frame Formats) в примере: 

// Communication Parameters: 8 Data, 1 Stop, No Parity

 

     
 

Сокращенно называют 8N1 - это формат по умолчанию для ПК.  

В таком формате передача байта начинается (естественно передающим устройством!) со "стартового бита" - это лог. "0" на ножке TXD для  USART МК и +5...+15 вольт для COM порта ПК на время одного бода. 

Время одного бода это результат деления 
1 сек на скорость передачи в бодах.

Затем на ножку TXD выводятся все 8 бит передаваемого байта начиная с бит_0. 

Каждый бит держится на TXD в течении времени передачи одного бода - за это время приемник должен определить и запомнить этот уровень. 

Далее идет "стоп бит"  - это лог. "1" на ножке TXD для  USART МК и -5...-15 вольт для COM порта ПК на время одного бода. 

 

На передачу одного байта в формате 
8N1
требуется время  -  10 бод.

 
     

 


Кусок кода выше я привел для примера. 

Я очень советую вам использовать 

Мастер начального кода компилятора - Он сам сгенерирует вам все в нужном виде и правильно настроит USART.

Главное - мастер покажет вам допустима ли ошибка в скорости 
передачи при использовании не UART'оских кварцев.

 

 

 

От слов к делу ... 

Запустите компилятор CodeVisionAVR, затем генератор начального, конфигурирующего кода программы для МК  - "CodeWizardAVR" - кликнув серую шестеренку слева от красного жучка... 

 

     
 

Подробно и с картинками работу с КодВизадом 
CodeVisionAVR я описал в задаче 1

 
     



Выберите в разделе Chip 

- МК ATmega16 и частоту кварца 11.059 МГц и 

 

Переходите на закладку USART  

- сделайте такие установки:


 


 Поставьте 3 галочки :
 
- включить приемник (Ресивер), 
- прерывание по приему символа и 
- включить передатчик (Трансмиттер). 

Число 100 означает - создать буфер в оперативной памяти МК на 100 символов. 

     
 

Чтобы не терять приходящие от ПК символы и не загружать МК постоянной проверкой - не получен ли новый символ в UDR 

удобно 

- использовать прерывание номер 12 "USART Rx Complete"  (стр. 43 ДШ) 
  его  вызывает завершение приёма символа в регистр UDR  и еще 

- создать буфер в который МК может в функции обработчике прерывания 
  12 положить принятый символ. 

А когда по программе понадобится или МК освободится от другой задачи,
он сможет  брать символы уже из этого буфера. 

Буфер устроен по принципу FIFO "фёст ин - фёст аут" а по-русски:  "первый пришел первый вышел" это значит что байт который пришел в FIFO буфер первым, первым же и выходит из него. 

 

FIFO - это что-то типа трубы с одной стороны загружаемой шарикам диаметром чуть меньше внутреннего диаметра трубы и вынимаемыми с другой стороны трубы. Емкость такого FIFO будет равна целому частному от деления длины трубы на диаметр шарика. Шарик - это байт.



Генератор начального кода компилятора CodeVisionAVR
сделает конфигурацию МК ПРАВИЛЬНО ! и быстро.

 
     


Буфер может быть ЛЮБОГО нужного вам размера - его ограничивает
лишь объем оперативной памяти МК. 

Советую вам сделать буфер в 2 раза больше того что вы считаете
нужным по предварительным прикидкам.

 

Скорость обмена данными - "БадРэйт" - установили 115200. 

Скорость USART может быть только одна в каждый
момент в МК и для приема и для передачи.
 

Если вам нужно принимать на скорости отличной от передачи то вы не сможете это делать одновременно и должны будете по необходимости включать либо передатчик либо приемник и устанавливать нужную скорость. 

Но я бы посоветовал вам просто взять МК с двумя USART
например ATmega64 и ATmega128.

 

Больше ни чего менять в панели USART не нужно.

 

 

Переходим к закладке LCD - мы подключим жидкокристаллический индикатор на 2 строки по 16 символов с встроенным контроллером HD44780 - это очень распространенные индикаторы (см. стр. 1 курса).  

 

 

Для подключения LCD  вам достаточно указать желаемый порт МК и количество символов в строке. Количество строк указывать не нужно. 

С лева указаны выводы МК, а в правой колонке указаны выводы LCD - их нужно соединить между собой. Кроме того нужно соединить "земли" и подать питание на индикатор и подать напряжение контраста - делать это надо в соответствии с ДШ 
на LCD.

 

     
 

ATMEL сделал АпНоут  

ANM069 "How to Interface a LCD Display to a TSC80251 Microcontroller" 

советую скачать и почитать. 

 
     

 

В закладке PORTA   сделайте  PA3 выходом - мы можем использовать 
его для индикации различных событий при отладке.

 

 

Всегда предусматривайте простые средства диагностики вашего устройства не требующие дополнительного оборудования !  К выводу МК можно подключить светодиод и разным режимом его горения отображать разную информацию, а можно выводить какую либо информацию на эту ножку в формате rs232.

 

 

Теперь 

В меню файл "КодВизада" выберите "генерэйт сэйв энд экзит",  и создайте в папке компилятора специальную папку для файлов задачи : 

C:\CVAVR\z5
  

Затем сохраните в ней созданный начальный код программы  usart.c  
и файл проекта  
z5.prj  

 

Посмотрите текст программы созданный 
генератором
самостоятельно. 

Вам уже многое должно быть понятно !

Си для МК на стр. 5 курса

 

 

Программа.

 

Рассмотрим участок программы создающий буфер 
для принимаемых  МК по USART символов.

 

     
 

/*****************************************************
Chip type : ATmega16
Program type : Application
Clock frequency : 11,059000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256

*****************************************************/

#include <mega16.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x1B
;PORTA
#endasm

#include <lcd.h>

#define
RXB8 1
#define
TXB8 0
#define
UPE  2
#define
OVR  3
#define
FE   4
#define
UDRE 5
#define
RXC  7

#define
FRAMING_ERROR (1<<FE)
#define
PARITY_ERROR (1<<UPE)
#define
DATA_OVERRUN (1<<OVR)
#define
DATA_REGISTER_EMPTY (1<<UDRE)
#define
RX_COMPLETE (1<<RXC)

 
     


Как я рассказывал на странице 5  "язык Си для МК" - программа на Си начинается с заголовка, затем вставляются тексты внешних файлов-библиотек с помощью команды препроцессора #include <текстовый файл>  

Затем с помощью первого блока определений #define компилятору сообщены номера битов по ДШ используемых в программе при работе с USART

 

 

Определения отдельных битов есть в компиляторах ICC, IAR 
и других,
но их нет в CodeVisionAVR поэтому я сделал для вас заголовочный файл m8_128.h  - скачайте его добавьте 
в программу вот так:

#include <mega16.h> //обычный хидер

#include <
m8_128.h> //мой хидер для битов

Теперь вы сможете использовать примеры
на Си из ДШ прямо так как они там написаны !

 

Второй блок определений #define делает программу более понятной и читаемой человеком давая осмысленные названия малопонятным битовым маскам 

например:  понятная человеку фраза  DATA_REGISTER_EMPTY в тексте программы на Си будет заменена препроцессором перед компиляцией на битовую маску   (1<<UDRE)  с помощью которой можно проверить  событие "регистр данных пуст" определяя состояние бита  UDRE.

 

     
 

Битовая маска   (1 << Название_бита_по_ДШ)

Это число у которого все биты равны "0" а бит с номером 
как номер бита
Название_бита_по_ДШ  равен "1". 

Получается маска сдвигом числа 1 из позиции бит_0 в лево на 
количество бит как номер бита
Название_бита_по_ДШ 

Подробнее про операции над битами в задаче 1 курса.

Битовая маска может иметь несколько единиц и нулей.

 
     


Теперь чтобы проверить свободен ли 
UDR - регистр данных USART - достаточно сделать логическое "И" числа в регистре  UCSRA  с маской  DATA_REGISTER_EMPTY

"Истина" будет означать что UDRE  равен "1" и значит регистр данных пуст.


Внимание!
Генератор начального кода CVAVR выдает 
бит
UPE - на самом деле в ATmega8 -16 -32 в регистре 
UCSRA бит_2 называется PE

На работу программы это не влияет.

 

 

Дальше ... 

 

     
 

// Буфер - USART Receiver buffer
#define RX_BUFFER_SIZE 100

char rx_buffer[RX_BUFFER_SIZE];

#if RX_BUFFER_SIZE<256
unsigned
char rx_wr_index, rx_rd_index, rx_counter;
#else
unsigned
int rx_wr_index, rx_rd_index, rx_counter;
#endif

// This flag is set on USART Receiver 
bit rx_buffer_overflow; // buffer overflow

 
     


В начале строка задающая нужный пользователю размер буфера - это 
может быть число от 1 (0 - это бессмысленно пожалуй)  до 65535 - это максимальное положительное число из двух байтов.


Благодаря использованию директивы препроцессора
#define 
мы сможем в случае необходимости изменения размера буфера, сделать это поменяв число
100 только в этой строке - не смотря на то, что используется оно в нескольких местах программы !  

 

Вывод: 

#define   - это удобно! и снижает вероятность ошибок. 
Позволяет просто модифицировать программу - используйте !

 

Следующей строкой объявлен символьный массив : 

char rx_buffer[размер массива в символах];

размером по заказанному нами буферу. 

Символьный в нашем случае - потому что char указывает на типа данных -
беззнаковый символьный - это числа от 0 до 255 - по таблице ASCII им
соответствуют определенные символы  - (таблицу ASCII  см. стр. 5 курса).


Напомню:

В массиве нумерация элементов начинается с НУЛЯ !
Значит первый элемент этого массива  на 100 элементов:         

rx_buffer[0]        а последний :         rx_buffer[99]

 

 

     
 

Далее очень интересно ! 

Обратите внимание что и в директивах препроцессора можно использовать конструкцию - 
if  else    

#if условие 
подставить в текст программы если условие "истина"
#else
подставить если условие "ложь"
#endif

только не нужны скобки (   ) и {   }, перед ключевыми словами ставьте 
знак  #  и закончить конструкцию нужно так как в примере !

Используйте!   

в любом месте программы где нужно.

 
     


С помощью этой конструкции в зависимости от размера буфера выбирается подходящий тип (байт или два байта)  трех глобальных переменных  необходимых для работы с буфером.

 

 

      СТОП  !

Вспомните и скажите вслух  - что такое глобальная переменная, каковы ее свойства, какие еще
типы переменных вы знаете.  
(подсказка

 

Последняя строка обсуждаемого куска кода (выше, на голубом фоне) 
объявляет битовую переменную 

bit rx_buffer_overflow;

это флаг (можно сказать - признак) переполнения буфера - если 

rx_buffer_overflow
    

"установится" т.е. станет "1"   -  плохо дело !  - мы долго не забирали символы из буфера и он переполнился, значит мы потеряли некоторые символы которые пришли раньше. 


Битовые переменные могут быть только глобальными ! 
т.е. они объявляются в начале  программы до фигурных скобок   {    }   и доступны программе в любом ее месте. 

Это в CVAVR
, а в других компиляторах с битовыми переменными
может быть и по другому. 

 

 

     
 

Совет !  Не жадничайте ! 

Используйте под флаги переменные типа char  вместо битовых. 

Они во всех компиляторах одинаковы - значит не запутаетесь.

Если вы выбрали правильный МК то с 
недостатком памяти вы не столкнетесь.

 
     

 

 

 

Дальше     

функция-обработчик прерывания № 12 : 

 

     
 

// 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;
    };

  };
}

 
     


Эта функция называется usart_rx_isr()  и вызывается при возникновении прерывания  USART_RXC (см. ДШ на МК) по приему символа в регистр  UDR   
это регистр данных USART, причем два регистра данных и приемника и 
передатчика называются одинаково. 

Т.е. программа МК перестает делать то что делала, сохраняет некоторые 
данные необходимые для продолжения работы с этого места после возврата 
из обработчика прерывания и начинает выполнять функцию обработчик 
прерывания  -     
usart_rx_isr()

 

     
 

Подробно о прерываниях рассказано 
на странице 3 курса

почитайте ...

 
     

 


Разберем что делает функция-обработчик прерывания 12.


Вначале объявлены две локальные переменные 
символьного типа 
  status    и data

Локальные - значит они объявлены сразу после 
открывающей скобки какой либо функции :  

{
  объявление локальных переменных 

далее остальное 
тело функции   
}  

Локальные переменные доступны только в той  функции в которой объявлены !   Значит в разных функциях могут быть локальные переменные с одинаковыми именами !  Но я не советую вам так делать -  запутаетесь.


Значение Локальных переменных без модификатора
static не сохраняется к следующему вызову функции, и нам не известно что в них содержится при создании - т.е. им нужно присвоить некоторое значение если мы не сделали это при объявлении. 

 

Вот программа и присваивает им значения в следующих двух строках:

status = UCSRA;
data = UDR;

В  status  копируется число из UCSRA  - это регистр 
                     управления и статуса - состояния  USART  (стр. 162 ДШ).

В  data  копируется число из UDR  - это регистр для принимаемых данных. 
(стр. 161 ДШ).


Затем  проводится  проверка правильно ли USART MK принял 
то что пришло на ножку RXD от ПК или другого устройства :

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
  Код программы написанный здесь будет  
выполнятся ТОЛЬКО если условие в           
скобках    if("истина")  -
       значит "НЕ НОЛЬ"

      };

 

     
 

Условие в скобках  у  if  довольно сложное

Используя сведения со страницы 5  "Си для МК" - попробуем 
разобраться что это условие означает.

Это важно! 
Обязательно разберитесь, поймите !

Структура условия такова:

if ( (   2 (  1  ))  3   )

оно состоит из нескольких выражений заключенных в скобки,  побитных логических операций в 1 и 2 и логической операции 3.

Начнем с самых глубоких скобок - красных  В них написано:

    FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN

Если вы внимательно читали задачу (я очень надеюсь!) то знаете, 
что каждое словосочетание благодаря директивам 
#define   в начале программы означает сдвиг единицы на некоторое количество позиций в лево - т.е. установку только некоторого одного бита в нулевом байте.  


Советую порисовать на бумажке байты и биты !


Т.е. мы имеем :

               число | число | число

Так как эти три числа соединены побитным "ИЛИ"  (напомню: это означает что только "0" и "0" дают "0") то в результате мы получим число где 3 бита будут равны "1"  - а номера этих битов будут 4, 3 и 2.


Теперь разберем какой результат даст 
вычисление содержимого синих скобок.

В них проводится побитная операция "И" (напомню: это означает что только "1" и "1" дают "1")  содержимого переменной status с тем числом которое является результатом красных скобок.

Значит если в status  (а значит и в регистре UCSRA)  -  хотя бы один из битов 4, 3 или 2 будет "установлен" - т.е. равен "1"  результат "И" будет не равен нулю. 

Нулю результат красных скобок  может быть равен - только если все три бита в UCSRA  были равны "0" - т.е. если данные были приняты без аппаратно детектируемой ошибки !

При этом же условии третье действие :  логическая операция ==0 
даст результат "истина" так как ноль и правда равен нулю, 


Значит :

То что написано в скобках  {  } после  if()  будет выполняться при безошибочном принятии данных.

 
     

 

Если же при приеме байта возникла любая из ошибок : 

FRAMING_ERROR    PARITY_ERROR     DATA_OVERRUN

то факт принятия данных  игнорируется и следующий код функции обработки прерывания закончен - т.е. программа выходит из прерывания не помещая "криво" принятый байт в буфер и возвращается к тому месту где возникло прерывание № 12.


 

Пусть ошибок не было, 
тогда ...

Выполняется код в скобках   {  }  после  if()  

Разберемся что он делает. 

Вот он со скобками :

     
 

{
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;
    };
};

 
     


Первая строка кода помещает принятый байт в буфер - конкретно в элемент массива rx_buffer  с  порядковым номером rx_wr_index   - этот номер называют индексом массива. 

В начале программы индекс 
rx_wr_index  равен нулю.  Почему ? 

А потому что  переменная  rx_wr_index 
                              была  объявлена как глобальная.  

 

     
 

Глобальным переменным при объявлении компилятор присваивает значение 0 , если конечно вы не присвоили ей явно другое значение, 

например вот так:

char kakayto_peremennaya = 78

"Какой то переменной" при объявлении присвоено значение   78

 
     


При следующих прерываниях по приему данных значение индекса будет меняться ! Если мы будем достаточно быстро забирать данные из буфера то иногда индекс будет опять становится  нулем.


Далее идет интересная конструкция :

if (++rx_wr_index == RX_BUFFER_SIZE)
     
{  // я добавил эти скобки
   rx_wr_index=0;
     
}; // для лучшей читаемости

я бы не советовал писать на Си начинающему так как накрапал мастер - но КодВизад создан профессионалом и потому нам нужно просто разобрать и понять что этот код делает.

Во первых я добавил фигурные скобки { }; - чтобы четко было видно 
какой код выполняется при "истине" в скобках  (    )  за 
if

 

 


Советую вам !      
Всегда дополняйте

if() while() for()   

Фигурными скобками   {      };

Разумные исключения :  while(1);  и  for(;;);

 


Итак :  Выражение-условие в  if()  означает: префиксный (так как ++ написаны перед переменной) инкремент переменной rx_wr_index  - т.е. добавление 1 к тому, что содержится в переменной. И затем проверяется равенство уже нового значения rx_wr_index с установленным нами размером буфера. 

 

     
 

Напомню что добавление некоторого числа к содержимому переменной не всегда увеличивает ее значение !

Если к переменной типа char  хранящей число 255 прибавить хотя бы 1
и результат записать в эту переменную - то в ней будет 0.

Вы очевидно понимаете что 255 + 1 = 256  

256 в двоичном виде 1 0000 0000  т.е. только бит_8 равен "1" а биты_7_0 все равны "0". При записи числа 256 в восьми-битную переменную типа
char   в нее поместятся как раз 8 нулей и поэтому в ней будет НОЛЬ.

 
     


Если перед
if индекс   rx_wr_index   был равен 99 то после инкремента индекс станет равен 100  и проверка на равенство с  RX_BUFFER_SIZE  даст "истину" - значит будет выполняться то, что написано в фигурных скобках после if  - это строка:

rx_wr_index = 0; // обнуляет индекс.  

Как видите индекс может стать нулем, как был в начале программы, и в том 
случае если мы долго не забирали символы из буфера и он переполнился !

 

     
 

Я бы вот так написал этот участок кода : 

rx_wr_index ++; // инкремент индекса

// сравнение уже увеличенного значения индекса
if (rx_wr_index == RX_BUFFER_SIZE)
     
{  
   rx_wr_index=0;
     
}; 

Мне кажется, что так - по шагам - писать и читать  
программу проще, особенно начинающим.

 
     

 

Далее еще одна проверка условия и действие по результату:

if (++rx_counter == RX_BUFFER_SIZE)
    {
    rx_counter=0;
    rx_buffer_overflow=1;
    };


Здесь ++ стоят перед переменной rx_counter - значит это префиксный инкремент  -  т.е. к значению переменной добавляется 1 и затем уже проверяется равно ли текущее содержимое переменной размеру буфера.

Если равно - значит буфер переполнился и будут выполнены две строки кода

rx_counter=0;
// Обнулить  счетчик принятых байтов в буфере

rx_buffer_overflow=1;
// Установить флаг переполнения буфера

     
 

Важно понять ! 

Операции ++  и - - изменяют то, что хранится в переменной !

Несмотря на отсутствие оператора присваивания.

 
     


Значит переменная 
rx_counter изменится на  1 
не зависимо от истинности условия в скобках у  
if()

 

Всё - обработка прерывания завершена. 

Теперь программа отправится в то место где она находилась 
в момент возникновения прерывания №12             

ГЛАВНОЕ !   Так как мы выполнили функцию обработчик прерывания до конца,  опять установится бит I в регистре SREG  - это разрешит прерывания в МК глобально и те прерывания которые разрешены индивидуально опять смогут прерывать ход программы.

 

Далее в тексте программы идет созданная мастером начального кода альтернативная обычно используемой в CodeVisionAVR функция "получить символ" - функция "получить символ из созданного буфера" - getchar()

НО !  Будет ли она включена препроцессором компилятора в компилируемый текст программы определяет конструкция из директив препроцессора:

#ifndef   #define   ...   #endif

Вы уже должны понимать как работает эта конструкция !

Поясню: Если мы делаем программу не для отладки на встроенном в CodeVisionAVR симуляторе терминала, а для реального МК или для внешнего симулятора - то в тексте программы не было определено:

#define _DEBUG_TERMINAL_IO_

поэтому будет выполнена строка : 

#define _ALTERNATE_GETCHAR_

и остальные строки на голубом фоне ниже будут включены в компилируемую программу препроцессором.

 

     
 

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
// взять символ из созданного буфера USART 

#define _ALTERNATE_GETCHAR_


#pragma used+

char getchar(void)
{
char data; // локальная переменная

while (rx_counter==0);

data = rx_buffer[rx_rd_index];

if (++rx_rd_index == RX_BUFFER_SIZE) 
{
rx_rd_index=0;
};  // я добавил {  }; для вящей читаемости

#asm
("cli")
--rx_counter;
#asm("sei")

return data;
}

#pragma used-

#endif

// Standard Input/Output functions
#include <stdio.h>

// Declare your global variables here

 
     

 

Подробно рассмотрим "тело" новой функции

Первая строчка :              char getchar(void)

говорит нам, что функция возвращает значение типа      char  
и при вызове не требует передачи в нее значений  - вот поэтому:  
(void)

Сразу после скобки  {  объявлена локальная (существующая и доступная только в этой функции) переменная символьного типа  char  с названием:    data  

Следующая строка: 

while (rx_counter == 0);

это цикл ожидания поступления символа в буфер. В ней программа будет "сидеть", а точнее "молотить" - пока нет прерывания и нет символа в буфере, ведь  rx_counter   это счетчик символов находящихся в буфере и пока буфер пуст эта переменная содержит 0 - вот цикл и повторяется ...

     
 

думаю вы уже понимаете что 

while (rx_counter == 0);

равносильно:

while (!(rx_counter));

Если не понятно, перечитайте Си для МК

Не откладывайте на потом !

 
     

 

Если в буфере были символы или появился символ, программа перейдет 
на следующую строку:

data = rx_buffer[rx_rd_index];

Тут все просто:  означает присвоить переменной слева от = результат выражения справа от =     Значит программа возьмет символ из буфера (из массива rx_buffer[]) с порядковым номером  rx_rd_index  и поместит его в   data 

 
Далее происходит увеличение индекса буфера на 1 и если результат будет равен размеру буфера - индекс обнуляется.

if (++rx_rd_index == RX_BUFFER_SIZE) 
{
rx_rd_index=0;
};  // я добавил {  }; для вящей читаемости

 

Так как мы считали символ из буфера нужно уменьшить число символов в нем подлежащих считыванию. 

#asm("cli")   // запретить прерывания глобально
--rx_counter; // вычесть 1 из rx_counter
#asm("sei")   // разрешить прерывания глобально

Обратите внимание что перед декрементом мы запрещаем прерывания, а после прерывания включаем опять.

Зачем ?    Вот фо ??? воскликнул бы англоязычный читатель ...

А затем, что в обработчике прерывания есть инкремент rx_counter  - и если на декременте возникнет прерывание мы можем зациклится в этом месте программы и получить ошибку в числе символов в буфере.

последняя строчка функции

return data;

означает что функция вернет то что находится в переменной  data

т.е. если мы напишем такой вызов функции:

nechto = getchar();

то после возврата из функции  в переменной  nechto  окажется то, что было помещено в   data   в функции.

 

Я подробно рассмотрел код создающий 
буфер для поступающих в МК данных.


Далее программа типична для создаваемых КодВизадом.

 

 

 


Как  принимать и отправлять данные
по USART AVR

 

Варианты кода для отправки и получения 
данных с помощью USART, например на ПК. 

Прочитайте самостоятельно раздел "Standard C Input/Output Functions
help  CodeVisionAVR (или того компилятора который будете использовать)
и включите заголовок - хидер  :

// Standard Input/Output functions
#include <stdio.h>

В нашей программе этот хидер уже подключен мастером !

 

1) отправить один символ типа  char  можно так: 

putchar('G');     
putchar(71);
putchar(0x47);

Любая из этих трех строк кода выводит на  ножку TXD число 71. На терминале ПК вы увидите соответствующий этому числу  символ  G 

В 16-тиричном виде это число 0x47 

Запомните форму записи чисел !

Таблица символов и их кодов есть на странице Си для МК

Кроме того один символ или число от 0 до 255 можно отправить с МК так:

while(!(UCSRA & (1<<UDRE)));
// дождитесь освобождение регистра передачи 

// Отправьте число одним из 3-х вариантов 
UDR =
'G'
UDR =
71;
UDR = 0x47;

 

Это же можно написать в одну строчку:

while(!(UCSRA & (1<<UDRE))); UDR = 'G';

Не рекомендую !
Считаю менее понятным начинающему и комментарий написать негде.



2) отправить строку символов можно вот так: 

putsf("Hello, world!"); 

На ножку TXD будут выведены все символы между кавычками (в примере их 13  посчитайте сами и убедитесь!)  и еще символ "перейти в начало следующей строки" - его код 0x0A а называется он LF от англ. "лайн фид"  - "новая строка".  И следующие данные будут выводится на терминале ПК (или на его симуляторе TTY в VMLAB или в CVAVR) с начала следующей строки.

 

     
 

Код 0x0A  (в начало новой строки - LF)  можно передать вот так:

putchar('\n');  или так   putchar(0x0A);

 
     


Строку символов для отправки можно записать и в виде последовательности шестнадцатеричных значений:  

putsf("\x41\x54\x44\x3e\x53\x4d\x31\x3b\x0D\x41"); 

На ножку TXD будут выведены все символы между кавычками (в примере их 10)
и еще символ 0x0A

Будет передаваться такая последовательность из 11 символов: 

ATD>SM1;<CR>A<LF>            цветом я отметил что это ОДИН символ ! 

в терминале VMLAB она будет выведена в две строки так:

ATD>SM1;<CR>
A<LF>

В терминале ПК не отображающем не печатные символы будет такой результат:  

ATD>SM1;
A

Символы (данные) которые МК будет передавать позже будут 
печататься уже с начала новой строки.

 

 


3) отправить информационные сообщения программы можно так: 

Вначале нужно описать эти сообщения - они буду размещаться во FLASH 
(в памяти программ) MK - т.е.
это не переменные а КОНСТАНТЫ !


flash char string_1[]="Prog Start";
flash char string_2[]="The END";

// Declare your global variables here 

Теперь вы можете выводить сообщения в нужном вам месте программы так:

printf(string_1);

На ножку TXD будут выведены все символы между кавычками
(в примере их 10
без добавления символа  0x0A

     
 

Что бы ваши сообщения гарантировано выводились с начала строки - добавьте символ 0x0A перед вашим сообщением вот так: 

flash char string_1[]="\nProg Start";

 
     

 

 

4) Вывести данные и поясняющий, оформляющий эти данные текст удобно  с помощью   printf() это мощная функция и полное ее описание почитайте в Help компилятора.

Примеры использования   printf() в папке   C:\CVAVR\Examples\

Например вывод температуры  :

char sign='+'; //датчик дал положительное число
int  temp=578; //число с датчика темп. LM75

printf("temp = %c%i.%u C\r\n",sign,temp/10,temp%10);


На терминал ПК будет выведено :

temp = 57.8 C

и курсор перейдет в начало новой строки.

Происходит это так: 

На терминал выводится то что находится между кавычками
"  " 

- текст temp =  выводится без изменений. Знак = окружают пробелы !

- вместо  %c будет вставлен символ из переменной   sign

- вместо  %i будет вставлен результат  temp/10 без дробной части 

- точка так и будет точкой 

- вместо %u будет результат (temp%10)  это дробная часть от деления

- далее пробел - он так и будет пробелом 

- затем символ C - он им же и останется

- потом стоит комбинация  \r\n - она выводит символы CR и LF их коды 0x0D  
  0x0A. Благодаря этому следующие данные будут выводится с начала строки через строчку ниже.

 



Внимание ! 

Чтобы отлаживать в PROTEUS функции printf() и scanf() зайдите в меню CVAVR - "прожект" - "конфига"  - "С компилер" и в списках этих функций выберите "Long..." или "Float..." и затем "ОК" конечно ...

 


 

     
 

Если UART MK настроен как сказано выше, то 

Вот пример для компиляторов ImageCraft ICC и  CodeVisionAVR использования функции   printf()

Если переменная   val    содержит число 166   то 

printf("val = %d",val);

Выведет на терминал ПК:       val = 166

и ...

printf("val = 0x%X",val);

Выведет на терминал ПК:    val = 0xA6


Подробней о 
printf() читайте в  Help  компилятора.

 
     

 

 

 

Примеры вывода различных чисел и строк и преобразование чисел в строки для вывода на USART и на LCD, в том числе и чисел с плавающей точкой - float, есть в проектах CVAVR и VMLAB  к этой задаче курса:     z5.rar

 

 

 

 

Прием данных поступающих
в USART  МК на ножку Rx


Наша программа автоматически принимает поступающие
данные и складывает в созданный буфер.


В том месте программы где вам нужно вставить наиболее давно 
пришедший в буфер символ (число, байт) впишите такую строчку:

getchar() // get - взять  char - символ


3 примера :

gdvix = getchar();
/* наиболее старый символ из буфера 
поместить в некоторую переменную gdvix  */

if (getchar() == 'G'){
/* выполнить код в скобках {...} если наиболее 
старый символ из буфера окажется буквой  G  */

                     };

while (getchar() != 'F');
/* взять из буфера наиболее старый 
символ и если это не F то повторить действие, 
а если это F пойти на следующий код программы */

 

     
 

      Если вы ожидаете получения какого либо пакета данных, и знаете каким числом он должен начинаться - то есколькими строками аналогичного кода можно определить нужную последовательность поступающих данных.  Пример приема команд и их разбора есть в исходниках в апноуте AN696 microchip. Он в примерах PROTEUS есть !

 
     


                    

if (rx_counter) {
/* выполнить ЭТОТ код если в буфере есть не считанные символы, данные */
                };

if (rx_counter > (RX_BUFFER_SIZE/2)) {
/* выполнить ЭТОТ код если буфер уже 
заполнен больше чем на половину */

                };

 

Что бы вывести самый старый символ из 
   буфера на ножку TXD напишите так:


putchar(getchar());

Эту строчку  и три первых примера выше - можно использовать 
и без буфера, но программа будет засиживаться в них (и занимать процессор вычислением) до тех пор пока не будет получен символ ! 
Будет ждать данные ...

Если написать так :

while(1){
putchar(getchar());
        };

то  МК будет отправлять приходящее на ножку RXD на ножку TXD   - так
можно проверить работоспособность соединения USART с компьютером.

Вы сможете попробовать это в симуляции !

 

 

 

 

Как  выводить данные на 
символьный LCD  - ЖКИ

Загрузите 1 страничку с описанием команд управления ЖКИ LCD 
на контроллере HD44780 и совместимых с ним.

Советую посмотреть АпНоут ANM069 от ATMEL


Для использования недорогого LCD нужно

- указать компилятору к каким ножкам МК он подключен в устройстве.

Вот наша (типовая) схема включения:


 

- указать компилятору сколько символов в строке имеет LCD дисплей.

-
в реальном LCD надо отрегулировать потенциометром (переменным резистором) контраст ( обычно на выводе 3 напряжение около 1.3 вольт ) и возможно (уточняйте в даташит на конкретно ваш LCD) включить подсветку.


Всё это любезно сделал для нас генератор начального кода CVAVR

// Alphanumeric LCD Module functions

#asm
.equ __lcd_port=0x1B ;PORTA
#endasm 

#include <lcd.h

// подключить"хидер"(заголовок,библиотеку)для LCD


А уже в программе строка: 

lcd_init(16);

инициализирует именно ЖКИ (LCD) где 16 символов на строку 

Мы можем указать в какую позицию выводить символ вот так:

lcd_gotoxy(4,1);

и вывод символов начнется с 5-й  позиции во второй строке.

Счет строк и символов начинается с НУЛЯ !

 

Давайте добавим в нашу программу вывод приветствия на LCD


lcd_gotoxy(5,0);

lcd_putsf("Hello");

lcd_gotoxy(2,1);

lcd_putsf("avr123.nm.r");

lcd_putsf("u");

 

В результате на LCD будет выведен такой текст :

 

это скриншот симуляции в VMLAB    

Смотрите - "чекбокс" "Break on com..." позволяет останавливаться 
симуляции при ошибке в командах на LCD.

Внимание !   Я специально разделил вывод   ru  чтобы показать, что следующий символ  u  выводится в позицию следующую за последним выведенным символом.


Прочитайте раздел LCD Functions  в Хлпе компилятора!


Очистить экран ЖКИ вы можете вызвав функцию:

lcd_clear();

Вывести символ, например F на ЖКИ

lcd_putchar('F');

Вывести на LCD строку символов из памяти программ  MK можно вот так:

lcd_putsf(string_1);

Объявление и текст этой строки были даны выше !

 

 
Примеры вывода различных чисел и строк и преобразование чисел в строки для вывода на USART и на LCD, в том числе и чисел с плавающей точкой - float, есть в

Архив с проектами CVAVR  и  VMLAB к задаче  5

  

 

Изучите их внимательно !
                 
Посимулируйте  вволю ...

Комментарии очень подробны.

 

При остановках симуляции в  VMLAB просто нажимайте на светофор ...  

Терпение! инициализация ЖКИ в симуляторе дело не быстрое. 

Посмотрите симулируя прогу в VMLAB осциллограммы приема и отправки данных по USART.

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

 

 

 

Как выводить на LCD русские буквы смотрите в FAQ по AVR

Вот результат:

 

 

     
 

Вы можете использовать один   
LCD  в нескольких устройствах !
  

Подключая его через разъем при необходимости. 

Для этого вам нужно сделать любой свободный вывод МК  PxN - входом с подтяжкой, и в разъеме от LCD поставить перемычку с этого "пина" на GND.
 
Если вы подключите LCD к вашему устройству - ножка P
xN заземлится перемычкой - значит на ней появится "0".

Теперь нужно в программе поместить ВСЕ строки работающие 
с  LCD  внутрь  скобок  {      }    у  оператора 
if  вот так:

if(!(PINX & (1 << N)){
    /*  тут код работающий с LCD 
    Он будет выполняться только 
       если на
PxN есть "0"       */
                                                     }

Если LCD не подключен, то на PxN будет "1" и программа не будет выполнять  код работающий с  ЖКИ  индикатором. 

 
     

 

Так же вы можете работать с другими
опционально подключаемыми к
МК устройствами !

 

 

 

Алфавитно-цифровые ЖК-модули фирмы Data Vision

Разрешение Модель Размер модуля Размер символа
8x2 DV0802 58.0x32.0x10.0 2.945x5.545
16x1 DV16100 80.0x36.0x10.0 3.07x6.56
DV16110 122.0x33.0x10.0 4.84x8.06
DV16120 151.0x40.0x14.7 14.5x6.0
16x2 DV16210 122.0x44.0x10.0 4.84x8.06
DV16230 85.0x30x10.0 2.78x4.89
DV16235 85.0x35.0x10.0 2.95x5.55
DV16236 85.0x36.0x10.0 2.95x5.55
DV16244 84x44.0x10.0 2.95x5.55
DV16252 80x36.0x10.0 2.78x4.89
DV16257 85.0x33x10.0 2.78x4.89
DV16275 100.0x39x13.0 4.07x7.76
DV16276 100.0x39x13.0 4.07x7.76
16x4 DV16400 87.0x60.0x10.0 2.95x4.75
20x1 DV20100 182.0x36x10.0 6.70x9.40
20x2 DV20200 116.0x36.0x10.0 3.20x5.55
DV20210 180.0x40.0x10.5 6.00x9.66
DV20211 182.5x60.0x20.0 5.9x12.7
DV20220 109x39.0x10.0 3.20x5.55
DV20206-1 86.0x39.0x14.0 3.2x5.55
20x4 DV20400 98.0x60.0x10.0 2.95x4.75
DV20410 146.0x63x10.5 4.84x9.22
24x2 DV24200 118.0x36.0x10.0 3.20x5.55
40x2 DV40200 182.0x34x10.0 3.20x5.55
40x4 DV40400 190.0x54.0x10.5 3.54x4.89


 

ЗАДАЧА    ОКОНЧЕНА !


     
 

Если вы еще не скачали ВСЕ АПНОУТЫ по AVR 

  это примеры применения МК AVR от ATMEL 

ПРОШУ ВАС, сделайте это ОБЯЗАТЕЛЬНО - 

ЭТО  отличный   СПРАВОЧНИК  сделанный  для ВАС !

 
     

 

    Если вам что-то не понятно, пожалуйста перечитайте 
задачу еще раз и просмотрите рекомендованный материал.  

 

 

Дальше ->    Задача 6

 

 

 

 

Все задачи-упражнения курса

 

Как устроен микроконтроллер AVR

 

 



 

          

 

 

 

 

 

ключевые слова: программирование микроконтроллеров, как написать программу для микроконтроллера, обучение программированию микроконтроллеров, микроконтроллеры atmega128, как запрограммировать микроконтроллер, как прошить микроконтроллер, отладка программы для AVR, моделирование работы электронных схем, электронные проекты, хобби, язык си для микроконтроллеров, язык программирования си
AT76C712 , AT76C713 , AT90CAN128 , AT90CAN128 Automotive , AT90CAN32 , AT90CAN64 , AT90PWM2 , AT90PWM3 , AT90S1200 , AT90S2313 , AT90S2323 , AT90S2343 , AT90S4433 , AT90S8515 , AT90S8535 , ATmega128 , ATmega1280 , ATmega1281 , ATmega16 , ATmega161 , ATmega162 , ATmega163 , ATmega164 , ATmega165 , ATmega168 , ATmega168 Automotive , ATmega169 , ATmega2560 , ATmega2561 , ATmega32 , ATmega323 , ATmega324 , ATmega325 , ATmega3250 , ATmega329 , ATmega3290 , ATmega406 , ATmega48 , ATmega48 Automotive , ATmega64 , ATmega640 , ATmega644 , ATmega645 , ATmega6450 , ATmega649 , ATmega6490 , ATmega8 , ATmega8515 , ATmega8535 , ATmega88 , ATmega88 Automotive , ATtiny11 , ATtiny12 , ATtiny13 , ATtiny15L , ATtiny2313 , ATtiny25 , ATtiny26 , ATtiny28L , ATtiny45 , ATtiny85

 

 

Проекты на микроконтроллерах AVR и PIC

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

        Широков Игорь Игоревич. "SignALL" - GSM сигнализация всем!
        Василь Урманчеев. Часы с коррекцией времени от GPS.
        Широков Игорь Игоревич. Контроллер доступа "Tiny KTM" на ATtiny45 - проще схемы не бывает!
        Топников Александр Сергеевич. МИКРОФАРАДОМЕТР.
        Фролов Дмитрий. Контроллер графического ЖКИ WG32240
        Буров Михаил. Редактор ресурсов RCE v1.1.1.1.
 

Лекции по курсу "Цифровые устройства"

1. Введение.

  1. Области применения и особенности цифровых устройств
  2. Описание цифровых схем.

2. Логические элементы.

  1. Логические элементы.
  2. Диодно-транзисторная логика (ДТЛ).
  3. Транзисторно-транзисторная логика (ТТЛ).
  4. Логика на комплементарных МОП транзисторах (КМДП).
  5. Согласование логических микросхем между собой.
  6. Регенераторы цифровых сигналов.

3. Арифметические основы цифровой техники.

  1. Системы счисления.
  2. Преобразование целых чисел из одной системы счисления в другую.
  3. Преобразование дробных чисел из одной системы счисления в другую.

4. Комбинационные устройства.

  1. Законы алгебры логики.
  2. Принципы аппаратурной реализации таблицы истинности.
  3. Декодеры
  4. Кодеры
  5. Мультиплексоры
  6. Демультиплексоры

5. Генераторы.

  1. Усилительные свойства инвертора.
  2. Осцилляторные схемы генераторов.
  3. Мультивибраторы.
  4. Особенности кварцевой стабилизации частоты генераторов.
  5. Одновибраторы.

6. Последовательностные устройства.
6.1 триггеры.

  1. Построение триггерных схем,
  2. RS-триггеры,
  3. D-триггеры,
  4. T-триггеры,
  5. JK-триггеры,

6.2 регистры.

  1. Параллельные регистры
  2. Последовательные регистры
  3. Универсальные регистры

6.3 Счетчики.

  1. Асинхронные двоичные счётчики
  2. Недвоичные счётчики с обратной связью
  3. Недвоичные счётчики с предварительной записью
  4. Синхронные кольцевые счётчики.
  5. Синхронные двоичные счётчики.

7. Индикаторы.

  1. Виды индикаторов.
  2. Светодиодные индикаторы.
  3. Жидкокристаллические индикаторы
  4. Динамическая индикация.

9. Синтезаторы частоты.

  1. Цифровой фазовый детектор
  2. Цифровой частотный детектор
  3. Цифровой фазовый компаратор.
  4. Цепи фазовой подстройки частоты.
  5. Умножители частоты

10. Микросхемы цифровой обработки сигналов.
10.1 Основные блоки цифровой обработки сигналов.

  1. Двоичные сумматоры
  2. Умножители
  3. Постоянные запоминающие устройства.
  4. Цифровые фильтры.
10.2 Микросхемы прямого цифрового синтеза радиосигналов.
  1. Фазовые аккумуляторы
  2. Полярные модуляторы
  3. Квадратурные модуляторы.
  4. Интерполирующие цифровые фильтры.

11. Примеры реализации цифровых устройств.
11.1 Электронные часы.

  1. Разработка структурной схемы
  2. Разработка принципиальной схемы
11.2 Последовательные порты.
  1. DSP-порт
  2. SPI-порт

 

 

 

 


AVR раз, два, три...   это просто!

действительно Краткий Курс !

МикроКонтроллеры AVR Начинающим "с нуля" 

Цифровая и вычислительная техника

Микропроцессоры и цифровая обработка сигналов

Цифровые устройства

Микропроцессоры

Книги в электронном варианте

Справочные данные

 

 

 

 

Курс лекций "Микропроцессоры"

1. Введение.

  1. Что такое микроконтроллеры, микропроцессоры и сигнальные процессоры.
  2. Области применения микроконтроллеров.

2. Принципы работы микропроцессоров.

  1. Сумматоры по модулю два. Построение многоразрядных арифметических сумматоров
  2. Виды двоичных кодов.
  3. Построение арифметико-логических устройств.
  4. Построение шинных формирователей.
  5. Масочные ПЗУ, ППЗУ, РПЗУ, ЭСППЗУ, FLASH - память
  6. Построение ОЗУ.
  7. Команды микропроцессора
  8. Блок обработки сигналов микропроцессора.
  9. Микрокоманды.
  10. Системная шина микропроцессора.
    Подключение ОЗУ и ПЗУ к системной шине микропроцессора.
    Дешифратор адреса.
    Понятие адресного пространства и распределения памяти микропроцессорного устройства.
  11. Подключение внешних устройств к микропроцессору.
  12. Принципы построения параллельного порта.
  13. Принципы построения последовательных портов
  14. Принципы построения таймеров.

3. Микроконтроллеры семейства MCS-51.

  1. Представители семейства MCS-51.
  2. Архитектура микроконтроллеров MCS-51.
  3. Система команд микроконтроллеров MCS-51. Виды адресации.
  4. Инструкции микроконтроллеров семейства MCS-51.
  5. Особенности построения параллельных портов микроконтроллеров MCS-51.
  6. Особенности построения памяти микроконтроллеров семейства MCS-51.
  7. Внутренние таймеры микроконтроллера, особенности их применения.
  8. Устройство и особенности применения последовательного порта микроконтроллеров семейства MCS-51.

4. Написание программ для микроконтроллеров

  1. Языки программирования для микроконтроллеров.
  2. Применение подпрограмм при программировании.
  3. Понятие подпрограммы процедуры и подпрограммы функции.
  4. Применение комментариев.
  5. Понятие структурного программирования.
  6. Понятие многофайлового программирования.
  7. Понятие многомодульного программирования.
  8. Написание программ для микроконтроллеров
  9. Отладка программ для микроконтроллеров

5. Язык программирования высокого уровня C-51.

  1. Язык программирования C-51
  2. Структура программ на языке программирования C-51
  3. Символы языка программирования C-51.
  4. Идентификаторы и константы.
  5. Выражения в операторах.
  6. Операторы.
  7. Объявление простых переменных.
  8. Объявление массивов и структур.
  9. Указатели.
  10. Объявление подпрограмм.
  11. Области действия переменных.
  12. Построение многомодульных программ.
6. Язык программирования ASM-51.
  1. Основные определения.
  2. Правила написания операторов на языке ассемблер.
  3. Символы, идентификаторы и числа языка ASM-51.
  4. Директивы языка ASM-51.
  5. Реализация подпрограмм процедур и подпрограмм функций на языке ассемблер.
  6. Способы реализации структурных операторов на языке ассемблер.
  7. Построение многомодульных программ на языке программирования ASM-51.
  8. Использование сегментов в языке программирования ассемблер.
7. Отладка программного обеспечения микроконтроллерного устройства.

8. Проектирование цифровых устройств на микроконтроллерах

  1. Разработка структурной схемы.
  2. Разработка принципиальной схемы.
  3. Написание программы для разрабатываемого микропроцессорного устройства
  4. Пример проекта программы

 

 


AVR раз, два, три...   это просто!

действительно Краткий Курс !

МикроКонтроллеры AVR Начинающим "с нуля" 

 

Что такое микроконтроллеры, микропроцессоры и сигнальные процессоры.

Вся схемотехника разделяется на две большие области: аналоговую и цифровую Преимущества и недостатки этих технологий известны. Аналоговая схемотехника характеризуется максимальным быстродействием, малым потреблением энергии и малой стабильностью параметров. Цифровая схемотехника обладает прекрасной повторяемостью параметров. Это привело к её развитию в последние годы. В курсах электронных приборов рассматривались основные технологии производства цифровых микросхем: ТТЛ, ЭСЛ и КМОП, поэтому здесь особенности этих технологий рассматриваться не будут.

По мере развития цифровых микросхем их быстродействие достигло впечатляющих результатов. Наиболее быстрые из цифровых микросхем обладают скоростью переключения порядка 3..5 нс. (серия микросхем 74ALS), а внутри кристалла микросхемы, где нет больших ёмкостей нагрузки время переключения измеряется пикосекундами. Таким быстродействием обладают программируемые логические схемы и заказные БИС. В этих микросхемах алгоритм решаемой задачи заключён в их принципиальной схеме.

Часто для решаемой задачи не требуется такого быстродействия, каким обладают современные цифровые микросхемы. Однако за быстродействие приходится платить:

  1. Быстродействующие микросхемы потребляют значительный ток.
  2. Для решения задачи приходится использовать много микросхем, это выливается в стоимость и габариты устройства.

Первую задачу решает применение технологии КМОП цифровых микросхем (например микросхемы серий 1564, 74HC, 74AHC). Потребляемый ими ток зависит от скорости переключения логических вентилей. Именно поэтому в настоящее время подавляющее большинство микросхем выпускается именно по этой технологии.

Вторую задачу решают несколькими способами. Для жёсткой логики это разработка специализированных БИС. Использование специализированных БИС позволяет уменьшить габариты устройства, но стоимость его снижается только при крупносерийном производстве. Для среднего и малого объёмов производства такое решение неприемлемо.

Ещё одним решением уменьшения габаритов и стоимости устройства является применение программируемых логических схем (ПЛИС). Это направление активно развивается в настоящее время, но оно не входит в рамки рассмотрения данного курса.

Третий способ решения поставленной задачи заключается в том, что можно заставить одно очень быстродействующее устройство последовательно решать различные задачи, изменяя свою структуру во времени. Это микропроцессоры. В микропроцессорах возможен обмен предельного быстродействия на сложность реализуемого устройства. Именно по этой причине стараются максимально увеличить быстродействие микропроцессоров - это позволяет реализовывать все более сложные устройства в одном и том же объеме. Более того! В одном процессоре можно реализовать несколько устройств одновременно! Именно это решение задачи и рассматривается в данном учебном курсе.

В современном мире трудно найти область техники, где не применялись бы микропроцессоры. Они применяются при вычислениях, они выполняют функции управления, они используются при обработке звука и изображения. В зависимости от области применения микропроцессора меняются требования к нему. Это накладывает отпечаток на внутреннюю структуру микропроцессора. В настоящее время определилось три направления развития микропроцессоров:

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

Для управления малогабаритными и дешёвыми устройствами связи используются однокристальные микроЭВМ, которые в настоящее время называются микроконтроллерами. В микроконтроллерах наоборот, максимальное внимание уделяется именно габаритам, стоимости и потребляемой энергии.

Еще один класс микропроцессоров решает задачи, которые традиционно решала аналоговая схемотехника. Это сигнальные процессоры. К сигнальным процессорам предъявляются специфические требования. От них требуются максимальное быстродействие, малые габариты, легкая стыковка с аналого-цифровыми и цифро-аналоговыми преобразователями, большая разрядность обрабатываемых данных и небольшой набор математических операций, обязательно включающий операцию умножения-накопления и аппаратную организацию циклов.

Сайт управляется системой uCoz