Проектирование систем на базе микроконтроллера AVR

БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ  УНИВЕРСИТЕТ

МЕХАНИКО-МАТЕМАТИЧЕСКИЙ ФАКУЛЬТЕТ

 

 

 

 

 

 

 

 

 

Курсовая работа

на тему:

Проектирование систем на базе микроконтроллера AVR

 

 

 

 

Выполнил: студент

3 курса ММФ

Кенть Павел Геннадьевич

Руководитель:

Бухтояров Сергей Евгеньевич

 

 

 

 

 

Минск, 2012

 

Оглавление

Введение 3

Структура микроконтроллера 4

Простейшая программа. 7

Прерывания 8

Подключение дисплея (asm) 12

Программа для работы с дисплеем через COM-порт. 15

Литература 18

 

Введение

В современной электронике  микропроцессором называют специальную 
микросхему, которая предназначена для выполнения некоего набора сложных функций по управлению тем либо иным электронным устройством. 
Микропроцессор – это сердце любого компьютера. Но не только. Те же 
технологии, которые применяются в компьютерах, с успехом применяются 
и в более простых электронных устройствах.

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

Микроконтроллер (англ. Micro Controller Unit, MCU) — микросхема, предназначенная для управления электронными устройствами. Типичный микроконтроллер сочетает на одном кристалле функции процессора и периферийных устройств, содержит ОЗУ или ПЗУ. По сути, это однокристальный компьютер, способный выполнять простые задачи.

Для изучения мною были выбрана серия AVR т.к. это очень простые и удобные в использовании микроконтроллеры. Чтобы задействовать какое-нибудь периферийное устройства, понадобятся всего пара строчек кода, что позволяет разработчику сосредоточить свое внимание над самой задачей. Также, одно из преимуществ данных микроконтроллеров (а может быть и главное) является большое количество сред для разработки/отладки приложении, сформировавшиеся сообщества, огромное количество библиотек/проектов/примеров.

В своей работе я приведу  примеры программ, написанных на двух языках программирования: Assembler и C. Все программы на ассемблере будут написаны в среде AVRStudio, а программа на C будет написана в среде mikroC PRO for AVR. Для проверки правильности работы программ будет использоваться программа моделирования Proteus.

Структура микроконтроллера

Перед тем, как начать писать программы, нужно понять, из чего же состоит микроконтроллер. На рисунке 1.1 представлена структурная схема  типичного современного микроконтроллера.

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

Давайте рассмотрим типичные схемы, присутствующие в микроконтроллерах.

1. Центральное процессорное устройство (ЦПУ) — сердце микроконтроллера. Оно принимает из памяти программ коды команд, декодирует их и выполняет. ЦПУ состоит из регистров, арифметико-логического устройства (АЛУ) и цепей управления.

2. Память программ. Здесь хранятся коды команд, последовательность которых формирует программу для микроконтроллера.

3. Оперативная память данных. Здесь хранятся переменные программ. У большинства микроконтроллеров здесь расположен также стек.

4. Тактовый генератор. Этот генератор определяет скорость работы микроконтроллера.

5. Цепь сброса. Эта цепь служит для правильного запуска микроконтроллера.

6. Последовательный порт — очень полезный элемент микроконтроллера. Он позволяет обмениваться данными с внешними устройствами при малом количестве проводов.

7. Цифровые линии ввода/вывода. По сравнению с последовательным портом, с помощью этих линий возможно управлять одновременно несколькими линиями (или проверять несколько линий).

8. Таймер. Используется для отсчета временных интервалов.

9. Сторожевой таймер. Это специальный таймер, предназначенный для предотвращения сбоев программы. Он работает следующим образом: после запуска он начинает отсчет заданного временного интервала. Если программа не перезапустит его до истечения этого интервала времени, сторожевой таймер перезапустит микроконтроллер. Таким образом, программа должна давать сторожевому таймеру сигнал — все в порядке. Если она этого не сделала, значит, по какой-либо причине произошел сбой.[2]

Семейство микроконтроллеров  AVR довольно обширно. Оно делится на три группы: Classic, Tiny и Mega. Вообще говоря, для решения задачи может быть использован практически любой микроконтроллер этого семейства. Система команд для всех микроконтроллеров одинаковая, отличие составляет лишь усложнение или упрощение внутренней архитектуры и увеличение или уменьшение аппаратных ресурсов. Мной был выбран представитель группы Mega8-битный микроконтроллер ATMega8, так как он занимает среднее положение между сложностью внутренней архитектуры и наличием аппаратных ресурсов.

 

 Основные  параметры  ATMega8:

Flash

(Кбайт)

EEPROM

(байт)

SRAM

(байт)

Линий ввода-вывода

Fmax

(МГц)

Vcc

(В)

8

512

1024

23

16

2.7-5.5


 

Flash: объем внутренней памяти микроконтроллера, используемой в качестве памяти программ (память программ – пространство, которое содержит машинный код выполняемый микроконтроллером и полученный в результате трансляции специальной программной среды).

EEPROM: объем внутренней энергонезависимой памяти данных (память данных – пространство используемое микроконтроллером для временного хранения полученных в результате работы вычислений и прочих данных которые будут использованы в дальнейшем).

SRAM: объем внутренней энергозависимой памяти данных.

Линии ввода-вывода: фактически количество ножек микроконтроллера, с помощью которых он взаимодействует с внешним миром.

Fmax –  максимальное значение рабочей тактовой частоты микроконтроллера, чем она выше, тем соответственно он работает быстрее.

Vcc – питание необходимое для работы микроконтроллера, чем меньше значение питания тем меньше энергопотребление, тем эффективнее использование микроконтроллера.

Микроконтроллеры серии  AVR имеют так называемую Гарвардскую архитектуру, основной особенностью которой является наличие раздельной шины данных и шины команд.[3]

 

 

 

 

Простейшая программа.

Рассмотрим очень простой  пример: написать программу, которая  при первом нажатии на кнопку зажигает светодиод, а при повторном нажатии  тушит его.

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

 

.include "m8def.inc"  ;Подключение микроконтроллера ATMega8

.list 

.cseg     ; Выбор сегмента программного кода

.org  0   ; Устанеовка текущего адреса на ноль

 

.def temp = r16  ; Переименуем регистры для упрощения дальнейшего использования

.def rab  = r17  

ldi rab, 0

 

 

;-------------------------- Инициализация  портов Вода-Вывода

 

out  DDRD, temp ; Записываем ноль в DDRD (порт PD на ввод)

ldi  temp, 0xFF ; Записываем число FF в регистр temp

out  DDRB, temp ; Записываем это число в DDRB (порт PB на вывод)

out  PORTD, temp ; Записываем то же число в PORTB (потушить светодиод)

out  PORTB, temp ; Записываем его же в PORTD (включаем внутр. резисторы)

 

;-------------------------------------------------- Основной цикл

 

wait_off: in temp, PIND

sbrs temp, 0

rjmp wait_off

 

wait_on:  in temp, PIND

sbrc temp, 0

rjmp wait_on

 

sbrc rab, 3

rjmp vikl

vkl:  ldi rab,0b01010101  

 

out PORTB, rab

ldi rab, 0xFF

rjmp wait_off

 

vikl:  ldi temp, 0xFF

out PORTB, temp

ldi rab, 0

rjmp wait_off

 

Принцип работы очень простой. В начале программы настраиваем порты ввода-вывода и переходим к основному циклу. Далее проверяем значение на PD0 (ножка 2) для определения, нажата ли кнопка. Значение rab показывает, что нужно делать со светодиодом (зажигать или тушить), и соответственно, подавать нужные значения на порт В.  Метки wait_off и wait_on нужны для того, чтобы при удерживании кнопки в нажатом состоянии светодиод не моргал.

 

 

 

 

Прерывания

Не будет преувеличением утверждать, что основное занятие  почти любого 
современного вычислительного устройства, от простенького контроллера 
стиральной машины до "навороченного" ноутбука — ожидание и обработка 
неких событий. Это могут быть сигналы от других устройств, посылаемые 
в автоматическом режиме, а также действия пользователя. Как можно обнаружить и обработать такие события?

Наиболее универсальный  способ, который применяется в  системах всех 
уровней, — организация основной программы в виде бесконечного цикла. 
Внутри этого цикла тем или иным способом отслеживается возникновение 
неких событий — такой цикл, например, представляет собой почти любая 
Windows-программа (как и Windows в целом). В основе такого способа лежит 
один и тот же принцип: при наступлении события устанавливается определенное значение некоей переменной, часто именуемой флагом; в простейшем 
случае это может быть один бит в специально отведенном регистре или в 
ячейке памяти (или даже непосредственно состояние вывода МК). Основная 
программа в цикле проверяет значение всех необходимых флагов, и при изменении какого-то из них переходит к соответствующей процедуре обработки события.

Внешних прерываний у большинства  МК AVR два или три. Естественно, они могут возникать независимо друг от друга. Внешнее прерывание — событие, которое наступает при наличии сигнала на одном из входов, специально пред- 
назначенных для этого (например, INTO и INT1).

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

Кратко рассмотрим особенности  этих режимов. Прерывание по низкому 
уровню (режим установлен по умолчанию, для его инициализации достаточно разрешить соответствующее прерывание) возникает всякий раз, когда на 
соответствующем входе присутствует низкий уровень. "Всякий раз" — это 
значит, что действительно всякий, т. е. если отрицательный импульс длится 
какое-то время, то прерывание, закончившись (т. е. когда выполнится соответствующий обработчик), повторится снова и снова, почти не давая основ- 
ной программе работать. Поэтому обычная схема использования этого режима — сразу же по возникновении в начале обработчика его запретить (процедура обработки при этом, раз уж началась, выполнится до конца) и разрешить 
опять только тогда, когда внешнее воздействие должно уже закончиться (на- 
пример, если это нажатие кнопки, то его следует опять разрешить по таймеру 
через одну-две секунды). Выход из обработки прерывания выполняется с помощью команды reti.

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

Программа работает аналогично предыдущей, отличие лишь в том, что  основной часть программы – бесконечный  пустой цикл, а остальное – обработка  прерываний. Также следует добавить, что за разрешение или запрет прерываний int0, int1 отвечают два старших бита регистра GICR.[5],[1]

 include "m8def.inc"

.list 

 

.def temp = r16 

.def rab  = r17; Определение главного рабочего регистра

 

.cseg     ; Выбор сегмента программного кода

.org  0   ; Устанеовка текущего адреса на ноль

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

rjmp reset ; Переход на начало программы

rjmp prer ;прерывание int0

rjmp prer ;прерывание int1

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reti

reset: 

ldi temp,low(RAMEND)

out SPL,temp

ldi temp, high(RAMEND)

out SPH,temp 

;-------------------------- Инициализация  портов ВВ

ldi  temp,0

ldi  rab, 0

out  DDRD, temp ; Записываем ноль в DDRD (порт PD на ввод)

ldi  temp, 0xFF ; Записываем число $FF в регистр temp

out  DDRB, temp ; Записываем это число в DDRB (порт PB на вывод)

out  PORTD, temp ; Записываем то же число в PORTB (потушить светодиод)

out  PORTB, temp ; Записываем его же в PORTD (включаем внутр. резисторы)

;----------------------------- Основной цикл-----------------------------------

ldi temp,0b11000000

out GICR,temp  ;Разрешаем прерывания int0,int1

sei

stop:

rjmp stop

 

prer:  clr  temp

out  GICR,temp ;Запрещаем прерывания int0,int1

sbrc  rab, 3

rjmp  vikl

vkl:  ldi  rab,0  

out  PORTB, rab

ldi  rab, 0xFF

ldi  temp,0b11000000

out  GICR,temp ;Разрешаем прерывания int0,int1

reti

vikl:  ldi  temp, 0b11010101

out  PORTB, temp

ldi  rab, 0

ldi  temp,0b11000000

out  GICR,temp ;Разрешаем прерывания int0,int1

reti

 

 

 

Подключение дисплея (asm)

Поставим перед собой  задачу написания программы на ассемблере, для работы с дисплеем. А именно программа будет выводить на дисплей  некоторый текст. Для написания программы, добавим библиотеку hd44780.asm,  текст которой представлен ниже. В ней происходит инициализация дисплея, выбор порта для подключения, настройки курсора и описание функций.

 

 

#define HD44780_CLEAR    0x01

#define HD44780_HOME    0x02

#define HD44780_ENTRY_MODE   0x04

#define HD44780_EM_SHIFT_CURSOR  0

#define HD44780_EM_SHIFT_DISPLAY 1

#define HD44780_EM_DECREMENT  0

#define HD44780_EM_INCREMENT  2

#define HD44780_DISPLAY_ONOFF   0x08

#define HD44780_DISPLAY_OFF  0

#define HD44780_DISPLAY_ON  4

#define HD44780_CURSOR_OFF  0

#define HD44780_CURSOR_ON  2

#define HD44780_CURSOR_NOBLINK  0

#define HD44780_CURSOR_BLINK  1

#define HD44780_DISPLAY_CURSOR_SHIFT 0x10

#define HD44780_SHIFT_CURSOR  0

#define HD44780_SHIFT_DISPLAY  8

#define HD44780_SHIFT_LEFT  0

#define HD44780_SHIFT_RIGHT  4

#define HD44780_FUNCTION_SET   0x20

#define HD44780_FONT5x7         0

#define HD44780_FONT5x10   4

#define HD44780_ONE_LINE   0

#define HD44780_TWO_LINE   8

#define HD44780_4_BIT   0

#define HD44780_8_BIT   16

#define HD44780_CGRAM_SET   0x40

#define HD44780_DDRAM_SET   0x80

.equ LCD_PORT  = PORTC

.equ LCD_DDR  = DDRC

.equ    LCD_PIN = PINC

.equ LCD_D4   = 0

.equ LCD_D5   = 1

.equ  LCD_D6   = 2

.equ LCD_D7   = 3

.equ LCD_RS  = 4

.equ LCD_EN  = 5

;------------------------------------------------------------------------------

LCD_WriteNibble:

sbi  LCD_PORT, LCD_EN

sbrs r16, 0

cbi  LCD_PORT, LCD_D4

sbrc r16, 0

sbi  LCD_PORT, LCD_D4

sbrs r16, 1

cbi  LCD_PORT, LCD_D5

sbrc r16, 1

sbi  LCD_PORT, LCD_D5

sbrs r16, 2

cbi  LCD_PORT, LCD_D6

sbrc r16, 2

sbi  LCD_PORT, LCD_D6

sbrs r16, 3

cbi  LCD_PORT, LCD_D7

sbrc r16, 3

sbi  LCD_PORT, LCD_D7

cbi  LCD_PORT, LCD_EN

ret

;------------------------------------------------------------------------------

LCD_WriteData:

sbi  LCD_PORT, LCD_RS

push r16

swap r16

rcall LCD_WriteNibble

pop  r16

rcall LCD_WriteNibble

clr  XH

ldi  XL,250

rcall Wait4xCycles

ret

;------------------------------------------------------------------------------

LCD_SetAddressDD:

ori  r16, HD44780_DDRAM_SET

rcall LCD_WriteCommand

ret

;------------------------------------------------------------------------------

LCD_Init:

sbi  LCD_DDR, LCD_D4

sbi  LCD_DDR, LCD_D5

sbi  LCD_DDR, LCD_D6

sbi  LCD_DDR, LCD_D7

sbi  LCD_DDR, LCD_RS

sbi  LCD_DDR, LCD_EN

cbi  LCD_PORT, LCD_RS

cbi  LCD_PORT, LCD_EN

ldi  r16, 100

rcall WaitMiliseconds

ldi  r17, 3

InitLoop:

ldi  r16, 0x03

rcall LCD_WriteNibble

ldi  r16, 5

rcall WaitMiliseconds

dec  r17

brne InitLoop

ldi  r16, 0x02

rcall LCD_WriteNibble

ldi  r16, 1

rcall WaitMiliseconds

ldi  r16, HD44780_FUNCTION_SET | HD44780_FONT5x7 | HD44780_TWO_LINE | HD44780_4_BIT

rcall LCD_WriteCommand

ldi  r16, HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF

rcall LCD_WriteCommand

ldi  r16, HD44780_CLEAR

rcall LCD_WriteCommand

ldi  r16, HD44780_ENTRY_MODE |HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT

rcall LCD_WriteCommand

ldi  r16, HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_ON | HD44780_CURSOR_BLINK

rcall LCD_WriteCommand

ret

;------------------------------------------------------------------------------

#ifndef F_CPU

   #error "F_CPU must be defined!"

#endif

#if F_CPU < 4000000

   #warning "F_CPU too low, possible wrong delay"

#endif

#define CYCLES_PER_US (F_CPU/1000000)

#define C4PUS (CYCLES_PER_US/4)

#define DVUS(x) (C4PUS*x)

;------------------------------------------------------------------------------

; Input : XH:XL - number of CPU cycles to wait (divided by four)

;-----------------------------------------------------------------------------

Wait4xCycles:

   sbiw   XH:XL, 1

   brne   Wait4xCycles

   ret

;-----------------------------------------------------------------------------

; Input : r16 - number of miliseconds to wait

 ;---------- WaitMiliseconds:

   push r16

 WaitMsLoop:

   ldi    XH,HIGH(DVUS(500))

   ldi    XL,LOW(DVUS(500))

   rcall  Wait4xCycles

   ldi    XH,HIGH(DVUS(500))

   ldi    XL,LOW(DVUS(500))

   rcall  Wait4xCycles

   dec    r16

   brne   WaitMsLoop

   pop    r16

   ret

;-----------------------------------------------------------------------------

; End of file

;-----------------------------------------------------------------------------

;**** Subroutine Register Variables

.def drem8u =r15  ;remainder

.def dres8u =r16  ;result

.def dd8u =r16  ;dividend

.def dv8u =r17  ;divisor

.def dcnt8u =r18  ;loop counter

;***** Code

div8u:

sub  drem8u,drem8u ; clear remainder and carry

ldi  dcnt8u,9  ; init loop counter

d8u_1: 

rol  dd8u  ; shift left dividend

dec  dcnt8u  ; decrement counter

brne d8u_2   ; if done

ret    ; return

d8u_2: 

rol  drem8u   ; shift dividend into remainder

sub  drem8u,dv8u  ; remainder = remainder - divisor

brcc d8u_3   ; if result negative

add  drem8u,dv8u ; restore remainder

clc    ; clear carry to be shifted into result

rjmp d8u_1  ; else

d8u_3: sec   ; set carry to be shifted into result

rjmp d8u_1

 

 

Подключив библиотеку hd44780.asm программа вывода текста становиться  очень простой. Работа программы  хорошо описана в комментариях.

 

 

.include "m8def.inc";Используем Мегу16

;======================================================

#define F_CPU (8000000)

;Здесь идёт определение  тактовой частоты. Нужно для 

;библиотеки задержек,используемой в этой либе.

;Частота в Герцах.

;======================================================

ldi r16,low(RAMend)

out SPL,r16

ldi r16,high(RAMend)

out SPH,r16

;Инициализация стека.  Обязательно!!!

;------------------------------------------------------

rcall lcd_init;Инициализация дисплея.

;------------------------------------------------------

ldi r16, 'K'      

rcall LCD_WriteData

ldi r16, 'e'

rcall LCD_WriteData

ldi r16, 'n'

rcall LCD_WriteData

ldi r16, 't'

rcall LCD_WriteData

ldi r16,0x40

rcall LCD_SetAddressDD

; Переходим ко второй  строке, поэтому запись будем  начинать с 40-го адреса

ldi r16, 'P' ;Выводим на дсплей следующую строку

rcall LCD_WriteData

ldi r16, 'a'

rcall LCD_WriteData

ldi r16, 'v'

rcall LCD_WriteData

ldi r16, 'e'

rcall LCD_WriteData

ldi r16, 'l'

rcall LCD_WriteData

;------------------------------------------------------

main:

;В главном цикле мы  ничего не делаем.

rjmp main

;------------------------------------------------------

.include "hd44780.asm"; Подключение библиотеки для работы с дисплеем.

 

 

 

 

 

Программа для работы с  дисплеем через COM-порт.

Как упоминалось выше, микроконтроллер  может работать и с компьютером  через последовательный порт UART (universal asynchronous receiver-transmitter, “универсальный асинхронный приемопередатчик”).

Поставим перед собой  задачу: микроконтроллер принимает  через COM-порт некоторую строку, вводимую пользователем на компьютере, а затем выводит ее на дисплей.

Рассмотрим программу  для микроконтроллера, написанную в  среде mikroC PRO for AVR на языке программирования С. В начале программы происходит инициализация дисплея – указывается, каким образом микроконтроллер будет соединен с дисплеем. Очень важно установить частоту приема-передачи данных одинаковой с частотой COM-порта. В нашей программе сделаем ее равной 9600. Программа записывает принятые данные, до прихода «!!!» – что будет являться признаком конца строки.

Программа на VisualBasic отправляет строку, введенную пользователем через UART, при этом дописывая в конце «!!!». Также программа подсказывает, что максимальное число символов, которые может корректно вывести дисплей, равняется 16.[5]

Прграмма на С

Программа на VisualBasic

sbit LCD_RS at PORTB2_bit;

sbit LCD_EN at PORTB3_bit;

sbit LCD_D7 at PORTB4_bit;

sbit LCD_D6 at PORTB5_bit;

sbit LCD_D5 at PORTB6_bit;

sbit LCD_D4 at PORTB7_bit;

 

sbit LCD_RS_Direction at DDB2_bit;

sbit LCD_EN_Direction at DDB3_bit;

sbit LCD_D7_Direction at DDB4_bit;

sbit LCD_D6_Direction at DDB5_bit;

sbit LCD_D5_Direction at DDB6_bit;

sbit LCD_D4_Direction at DDB7_bit;

int i,pos;

char text[20];

void main() {

LCD_Init();

LCD_Cmd(_LCD_CURSOR_OFF);

UART1_Init(9600);

while (1) {

      if (UART1_Data_Ready() == 1)

         {

         UART1_Read_Text(text, "!!!", 255);

         Lcd_Cmd(_LCD_CLEAR);

         LCD_Out(1,1,text);

         text[0]='\0';  }

       }}

Public Class Form1

 

    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)

 

    End Sub

 

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        SerialPort1.PortName = "COM2"

        SerialPort1.Open()

        Label4.ForeColor = Color.Green

        Label4.Text = "Connected"

    End Sub

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        SerialPort1.Write(TextBox1.Text)

        SerialPort1.Write("!!!")

    End Sub

 

    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged

 

        If (Len(TextBox1.Text) > 16) Then

            Label2.ForeColor = Color.Red

        Else

            Label2.ForeColor = Color.Black

        End If

        Label2.Text = Len(TextBox1.Text)

    End Sub

 

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        SerialPort1.Close()

        Label4.ForeColor = Color.Red

        Label4.Text = "Disconnected"

    End Sub

 

End Class


 

С помощью программы VSPE создадим виртуальную пару COM-портов (COM1 и COM2). К порту COM1 подключим микроконтроллер, а к COM2 будет подключаться пользователь.

 

Теперь осталось создать  проект в Proteus, не забыв установить частоту 9600.

Проверим правильность работы всех программ:

 

Литература

    1. Белов А. В. «Самоучитель разработчика устройств на микроконтроллерах AVR» – Наука и Техника, Санкт-Петербург, 2008.
    2. Голубцов М. С. «Микроконтроллеры AVR: от простого к сложному» – СОЛОН-Пресс, Москва, 2003.
    3. Евстисфеев А. В. «Микроконтроллеры AVR семейства Mega» – издательский дом «Додэка – XXI», Москва, 2007.
    4. Кравченко А. В. «10 практических устройств на AVR-микроконтроллерах» – издательский дом «Додэка – XXI», 2008.
    5. Ревич Ю. «Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера» - БВХ-Петербург, 2008.

Проектирование систем на базе микроконтроллера AVR