Разработка логической схемы реализации линии связи
Iom169. h — заголовочный файл, который ставит в соответствие константам PORTA и PORTB реальные адреса выводов конкретного контроллера (в нашем случае ATmega169). Вывод 2 используется для посылки и приёма Арбитру управляющих сигналов («Внимание», «Готов» ит.д.), а также для приёма информационного сообщения. AVR Studio — интегрированная среда проектирования программ для микроконтроллеров, которую… Читать ещё >
Разработка логической схемы реализации линии связи (реферат, курсовая, диплом, контрольная)
- Задание
- Описание работы порта А
- Описание работы порта B
- Создание проекта в AVR Studio
- Список использованной литературы
- Приложение
Задание
К общей шине (ОШ) подключены несколько абонентов, каждый из которых функционирует автономно в соответствии с управляющей информацией, полученной от специального устройства — арбитра общей шины. Эта шина включает 3 линии связи: одну информационную и две синхронизирующие. Передача информации ведется в последовательном коде. При этом синхроимпульсы С1 отмечают начало каждого байта, а С2 синхронизируют передачу отдельных битов. Основная тактовая частота 1 МГЦ. Длительность синхроимпульсов 0,25 мкс.
При необходимости связи арбитр вырабатывает общий для всех абонентов сигнал ВНИМАНИЕ и затем — АДРЕС нужного абонента. Этот абонент после идентификации своего адреса выдает в шину сигнал ГОТОВ либо ЗАНЯТ в зависимости от своего состояния. Получив сигнал готовности, арбитр сразу же формирует непрерывную многобайтную посылку — информационное сообщение (ИС), которое замыкается сигналом КОНЕЦ ПЕРЕДАЧИ. Приняв эту посылку, абонент отвечает сигналом КОНЕЦ ПРИЕМА при отсутствии ошибок передачи, либо сигналом ПОВТОРИТЬ ПЕРЕДАЧУ, если обнаружена ошибка. В последнем случае арбитр повторяет весь цикл связи заново. Информационное сообщение имеет символьный характер. Каждый символ занимает 1 байт (8 разрядов). Алфавит сообщений содержит всего 200 символов. Остающиеся 56 символов могут быть использованы в качестве сигналов связи: ГОТОВ, ВНИМАНИЕ и др.
Для реализации связи каждому абоненту придается интерфейсный модуль-контроллер связи. Сигналы ГОТОВ и ПОВТОРИТЬ-ПЕРЕДАЧУ вырабатываются контроллером по получении от своего абонента сигналов конца работы (КР) и ошибки передачи (ОП) соответственно.
ВНИМАНИЕ | |||
АДРЕС | |||
ГОТОВ | |||
ЗАНЯТ | |||
КОНЕЦ_ПЕРЕДАЧИ | |||
КОНЕЦ_ПРИЕМА | |||
ПОВТОРИТЬ_ПЕРЕДАЧУ | |||
Схема микроконтроллера.
Для программирования необходимой логики работы мы будем использовать 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
// Подключение заголовочного файла, который позволяет объявлять булевские переменные
#include
// Определение пользовательского типа данных 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); // Посылаем Арбитру, что Абонент ЗАНЯТ
}
}
}
}
}