Разработка логической схемы реализации линии связи

Тип работы:
Контрольная
Предмет:
Коммуникации, связь, цифровые приборы и радиоэлектроника


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Содержание

  • Задание
  • Описание работы порта А
  • Описание работы порта B
  • Создание проекта в AVR Studio
  • Список использованной литературы
  • Приложение

Задание

К общей шине (ОШ) подключены несколько абонентов, каждый из которых функционирует автономно в соответствии с управляющей информацией, полученной от специального устройства — арбитра общей шины. Эта шина включает 3 линии связи: одну информационную и две синхронизирующие. Передача информации ведется в последовательном коде. При этом синхроимпульсы С1 отмечают начало каждого байта, а С2 синхронизируют передачу отдельных битов. Основная тактовая частота 1 МГЦ. Длительность синхроимпульсов 0,25 мкс.

При необходимости связи арбитр вырабатывает общий для всех абонентов сигнал ВНИМАНИЕ и затем — АДРЕС нужного абонента. Этот абонент после идентификации своего адреса выдает в шину сигнал ГОТОВ либо ЗАНЯТ в зависимости от своего состояния. Получив сигнал готовности, арбитр сразу же формирует непрерывную многобайтную посылку — информационное сообщение (ИС), которое замыкается сигналом КОНЕЦ ПЕРЕДАЧИ. Приняв эту посылку, абонент отвечает сигналом КОНЕЦ ПРИЕМА при отсутствии ошибок передачи, либо сигналом ПОВТОРИТЬ ПЕРЕДАЧУ, если обнаружена ошибка. В последнем случае арбитр повторяет весь цикл связи заново. Информационное сообщение имеет символьный характер. Каждый символ занимает 1 байт (8 разрядов). Алфавит сообщений содержит всего 200 символов. Остающиеся 56 символов могут быть использованы в качестве сигналов связи: ГОТОВ, ВНИМАНИЕ и др.

Для реализации связи каждому абоненту придается интерфейсный модуль-контроллер связи. Сигналы ГОТОВ и ПОВТОРИТЬ-ПЕРЕДАЧУ вырабатываются контроллером по получении от своего абонента сигналов конца работы (КР) и ошибки передачи (ОП) соответственно.

ВНИМАНИЕ

217

11 011 001

АДРЕС

57

111 001

ГОТОВ

237

11 101 101

ЗАНЯТ

253

11 111 101

КОНЕЦ_ПЕРЕДАЧИ

114

1 110 000

КОНЕЦ_ПРИЕМА

174

10 101 110

ПОВТОРИТЬ_ПЕРЕДАЧУ

154

10 100 100

Схема микроконтроллера.

Для программирования необходимой логики работы мы будем использовать 3 из 8 выводов порта, А и все 8 выводов порта B

Описание работы порта А

На вывод 0 поступает сигнал синхронизации С1

На вывод 1 поступает сигнал синхронизации С2

Вывод 2 используется для посылки и приёма Арбитру управляющих сигналов («Внимание», «Готов» ит.д.), а также для приёма информационного сообщения.

Выводы 3−7 не используются и поэтому не показаны на схеме

Описание работы порта B

8 выводов порта B используются для параллельной передачи и приёма Абоненту управляющих сигналов («Ошибка передачи», «Конец работы» ит.д.), а также для пересылки информационного сообщения, которое идёт от Арбитра

порт линия связь схема

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

Работу программы будем проверять в эмуляторе AVR Studio 4. 13. 528

Компилировать программу будем в WinAVR 20 071 221

AVR Studio — интегрированная среда проектирования программ для микроконтроллеров, которую можно свободно скачать с сайта производителя www. atmel. com

WinAVR — программный пакет, содержащий в себе интересующий нас компилятор GNU GCC для C. WinAVR можно свободно скачать с сайта разработчиков http: //sourceforge. net/projects/winavr/

Для разбора задания установите сначала WinAVR, а потом AVR Studio. Порядок установки важен для того, чтобы AVR Studio установил в настройках проекта в качестве компилятора компилятор GNU GCC, входящий в состав WinAVR. Обе программы установите с параметрами по умолчанию.

Создание проекта в AVR Studio

Для создания проекта в AVR Studio необходимо зайти в меню Project - > Project Wizard - > New Project

В окне Project type выбираем AVR GCC потому что будем писать программу на языке C

В окне Project name вписываем произвольно название проекта, допустим mk

В окне Initial file вписываем main. c. Это будет главный файл проекта, где будет находиться функция main.

Жмём Next

В окне Debug platform выбираем AVR Simulator. В окне Device выбираем ATmega169

Жмём Finish

После создания проекта в AVR Studio необходимо зайти в меню Project - > Configuration Options - > General и выставить значение Optimization = - O0. Это отключит оптимизацию кода, которая нам не нужна при отладке программы.

Окно main. c содержит исходный текст программы (предварительно скопируйте код в это окно).

В окне I/O View можно наблюдать, а также изменять состояние портов, А и B.

Например сигнал С1 эмулируется в данной работе установкой в единицу PINA bit 0., а сигнал С2 эмулируется установкой в единицу PINA bit 1.

Значение PINA bit 2 эмулирует значения, которые нам приходят по информационной линии

В окне Watch можно следить за значениями переменных.

Список использованной литературы

1. Голубцов М. С., Кириченкова А. В. Микроконтроллеры AVR: от простого к сложному. — М.: «Солон-Пресс», 2004.

2. Шпак Ю. А. Программирование на языке C для AVR и PIC микроконтроллеров. — М.: «МК-Пресс», 2006.

3. Фрунзе А. В. Микроконтроллеры? Это же просто! — K.: «Додэка XXI», 2007.

4. Белов А. В. Самоучитель разработчика устройств на микроконтроллерах AVR. — М.: «Наука и техника», 2008.

5. Хартов В. Я. Микроконтроллеры AVR. Практикум для начинающих. — М.: МГТУ им. Н. Э. Баумана, 2007.

6. Джон Мортон Микроконтроллеры AVR. Вводный курс AVR: An Introductory Course. — К.: «Додэка XXI», 2006.

7. Евстифеев А. В. Микроконтроллеры AVR семейства Tiny. Руководство пользователя. — К.: Додэка XXI, 2007

Приложение

/*

Подключение заголовочного файла io. h, который в свою очередь подключит iom169. h

iom169. h — заголовочный файл, который ставит в соответствие константам PORTA и PORTB реальные адреса выводов конкретного контроллера (в нашем случае ATmega169)

Таким образом io. h позволяет работать с портами ввода-вывода

*/

#include < avr/io. h>

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

#include < stdbool. h>

// Определение пользовательского типа данных byte

typedef unsigned char byte;

// Константы, определённые для обращения к выводам порта А

#define C1 (PINA & 0×01) /* 0-вой вывод порта А, на который приходит сигнал С1 */

#define C2 (PINA & 0×02) /* 1-вой вывод порта А, на который приходит сигнал С2 */

#define DATAIN ((PINA & 0×04) > > 2) /* 2-вой вывод порта А, на который приходит информация. Чтение информации из порта */

#define DATAOUT (x) PORTA = (PORTA & ~ (0×04)) | (x < < 2) /* 2-вой вывод порта А, на который приходит информация. Ввод информации в порт */

// Символы сигналов связи варианта задания на курсовой проект #4

#define ATTENTION 217 // Внимание

#define ADDRESS 57 // Адрес

#define READY 237 // Готов

#define BUSY 253 // Занят

#define END_OF_TRANSFER_SEQUENCE 114 // Конец передачи

#define END_OF_RECEIVE 174 // Конец приёма

#define REPEAT_TRANSFER 154 // Повторить передачу

// Символы сигналов связи от Абонента

#define END_OF_WORK 1 // Конец работы

#define TRANSFER_ERROR 2 // Ошибка передачи

// Глобальные переменные

byte frameFromArbiter = 0;

bool abonentStateReceived = false;

bool frameCameFromArbiter = false;

bool AddressCameFromArbiter = false;

bool frameToAbonentWasSent = false;

bool requestToAbonentWasSent = false;

bool stateOfAbonentWasSentToArbiter = false;

bool DataMessageRefered = false;

int abonentState = 0;

// Получаем побитово байт от Арбитра

void ReceiveFrameFromArbiter ()

{

static int C2Count = 0;

static bool C1Came = false;

static bool C2Out = true;

if (C1) // Если пришёл сигнал С1,{

C1Came = true; // запоминаем что сигнал С1 приходил

}

if (C1Came) // Если сигнал С1 приходил

{

if (C2 & & C2Out) // Если сигнал С2 пришёл,

frameFromArbiter = (frameFromArbiter & ~ (1 < < C2Count))

if (C2Count == 8) // Если пришло 8 сигналов С2, значит мы приняли целиком байт

{

C2Count = 0; // Обнуляем количество сигналов С2

C1Came = false; // Запоминаем что пришёдший после С1 байт уже обработан, ждём следующий С1

C2Out = true;

frameCameFromArbiter = true; // Запоминаем что байт пришёл

}

if (! C2) { // Если сигнал С2 ушёл

C2Out = true; // Запоминаем, что сигнал С2 ушёл

}

}

}

// Ждём поступления от Арбитра адреса микроконтроллера

void WaitAddressFromArbiter ()

{

DDRA = 0×00; // Указываем микроконтроллеру настроить все выводы на приём информации

bool attentionCame = false;

ReceiveFrameFromArbiter (); // Получить байт от Арбитра

if (frameCameFromArbiter) // Если байт от Арбитра пришёл

{

if (attentionCame) // Если сигнал Внимание уже приходил

{

if (frameFromArbiter == ADDRESS) // И пришедший байт равен адресу микроконтроллера

{

AddressCameFromArbiter = true; // Запоминаем, что адрес пришёл

}

attentionCame = false;

}

if (frameFromArbiter == ATTENTION) // Если пришёл байт равный сигналу Внимание

{

attentionCame = true; // Запоминаем, что приходил сигнал Внимание

}

frameCameFromArbiter = false; // Записываем, что мы уже обработали пришедший байт

}

}

// Посылаем параллельно байт Абоненту

void SendFrameToAbonent (byte sendFrame)

{

static bool C1Came = false;

if (C1) // Если пришёл сигнал С1,{

C1Came = true; // запоминаем что сигнал С1 приходил

}

if (C1Came) // Если сигнал С1 приходил

{

PORTB = sendFrame; // Выдаём на выводы порта B байт

}

if (! C1 & & C1Came) // Если сигнал С1 ушёл и приходил

{

frameToAbonentWasSent = true; // Запоминаем что байт был отослан

C1Came = false;

}

}

// Посылаем Абоненту запрос о его состоянии

void SendToAbonentRequestAboutAbonentState ()

{

DDRB = 0xFF; // Указываем микроконтроллеру настроить все выводы порта B на вывод информации

SendFrameToAbonent (READY); // Посылаем байт ГОТОВ Абоненту

if (frameToAbonentWasSent) // Если байт был послан

{

requestToAbonentWasSent = true; // Запоминаем, что запрос Абоненту был послан

}

}

// Получаем от Абонента его состояние

void ReceiveFromAbonentAbonentState ()

{

DDRB = 0×00; // Указываем микроконтроллеру настроить все выводы порта B на приём информации

static bool C1Came = false;

if (C1) // Если пришёл сигнал С1,{

C1Came = true; // запоминаем что сигнал С1 приходил

}

if (C1Came) // Если сигнал С1 приходил

{

abonentState = PINA; // Выдаём на выводы порта B байт

}

if (! C1 & & C1Came) // Если сигнал С1 ушёл и приходил

{

abonentStateReceived = true; // Запоминаем что получили состояние Абонента

C1Came = false;

}

}

// Посылаем Арбитру состояние Абонента

void SendToArbiterAbonentState (byte frame)

{

DDRA = 0×04;

static int C2Count = 0;

static bool C1Came = false;

static bool C2Out = true;

if (C1) // Если пришёл сигнал С1,{

C1Came = true; // запоминаем что сигнал С1 приходил

}

if (C1Came) // Если сигнал С1 приходил

{

if (C2 & & C2Out) // Если сигнал С2 пришёл,

{

DATAOUT ((frame & (1 < < C2Count)) > > C2Count); // Записываем очередной бит на информационную линию

C2Count++; // Считаем номер пришёдшего сигнала С2

C2Out = false; // Запоминаем, что С2 пришёл, но ещё не уходил

}

if (C2Count == 8)

{

C2Count = 0; // Обнуляем количество сигналов С2

C1Came = false; // Запоминаем что пришёдший после С1 байт уже обработан, ждём следующий С1

C2Out = true;

stateOfAbonentWasSentToArbiter = true; // Запоминаем, что состояние Абонента было отослано Арбитру

}

if (! C2) { // Если сигнал С2 ушёл

C2Out = true; // Запоминаем, что сигнал С2 ушёл

}

}

}

// Получаем информационное сообщение от Арбитра и пересылаем Абоненту

void ReceiveDataMessageFromArbiterAndReferToAbonent ()

{

DDRA = 0×00; // Указываем микроконтроллеру настроить все выводы на приём информации

ReceiveFrameFromArbiter (); // Получить байт от Арбитра

if (frameCameFromArbiter) // Если байт от АРбитра пришёл

{

SendFrameToAbonent (frameFromArbiter); // Посылаем байт Абоненту

frameCameFromArbiter = false; // Запоминаем, что мы обработали байт, пришедший от Арбитра

if (frameFromArbiter == END_OF_TRANSFER_SEQUENCE) // Если пришёдший байт совпадает с символом КОНЕЦ ПЕРЕДАЧИ

{

DataMessageRefered = true; // Запоминаем что информационное сообщение переслали

}

}

}

int main (void)

{

while (1) // Запускаем бесконечный цикл

{

if (! AddressCameFromArbiter) // Если адрес МК ещё не пришёл от Арбитра,

{

WaitAddressFromArbiter (); // ждём

}

if (AddressCameFromArbiter) // Если от Арбитра пришёл адрес МК

{

SendToAbonentRequestAboutAbonentState (); // посылаем Абоненту запрос о его состоянии

if (requestToAbonentWasSent) // Если запрос о состоянии Абонента был послан

{

ReceiveFromAbonentAbonentState (); // получаем ответ

}

if (abonentStateReceived) // Если получили состояние Абонента,

{

if (abonentState == END_OF_WORK) // и состояние равно КОНЕЦ РАБОТЫ,

{

SendToArbiterAbonentState (READY); // посылаем Арбитру сигнал ГОТОВ

if (stateOfAbonentWasSentToArbiter) // Если состояние Абонента отослалось Арбитру

{

ReceiveDataMessageFromArbiterAndReferToAbonent (); // Начинаем принимать информационное сообщение от Арбитра и пересылать его Абоненту

if (DataMessageRefered) // Если информационное сообщение было отослано

{

SendToAbonentRequestAboutAbonentState (); // Посылаем Абоненту запрос о его состоянии

if (requestToAbonentWasSent) // Если запрос о состоянии Абонента был послан,

{

ReceiveFromAbonentAbonentState (); // ждём ответ

}

if (abonentStateReceived) // Если получили состояние Абонента,

{

if (abonentState == TRANSFER_ERROR) // Если состояние Абонента равно ОШИБКА ПЕРЕДАЧИ

{SendToArbiterAbonentState (REPEAT_TRANSFER); // Посылаем Арбитру сигнал ПОВТОРИТЬ ПЕРЕДАЧУ

}

else // Если ошибки не произошло

{

SendToArbiterAbonentState (END_OF_RECEIVE); // Посылаем Арбитру сигнал КОНЕЦ ПРИЁМА

}

}

}

}

}

else // Если состояние не равно КОНЕЦ РАБОТЫ

{

SendToArbiterAbonentState (BUSY); // Посылаем Арбитру, что Абонент ЗАНЯТ

}

}

}

}

}

ПоказатьСвернуть
Заполнить форму текущей работой