Автор работы: Пользователь скрыл имя, 22 Февраля 2014 в 20:21, курсовая работа
К общей шине (ОШ) подключены несколько абонентов, каждый из которых функционирует автономно в соответствии с управляющей информацией, полученной от специального устройства – арбитра общей шины. Эта шина включает 3 линии связи: одну информационную и две синхронизирующие. Передача информации ведется в последовательном коде. При этом синхроимпульсы С1 отмечают начало каждого байта, а С2 синхронизируют передачу отдельных битов. Основная тактовая частота 1 МГЦ. Длительность синхроимпульсов 0,25 мкс.
Задание……………………………………………………………………….3
Схема микроконтроллера…………………………………………………...4
Описание работы………………………………………………………...…..4
Создание проекта в AVR Studio…………………………………………….5
Приложение………………………………………………………………….6
Список использованной литературы………………………………………13
Задание……………………………………………………………
Схема микроконтроллера……………………………………
Описание работы………………………………………
Создание проекта в AVR Studio…………………………………………….5
Приложение……………………………………………………
Список использованной литературы………………………………………13
Задание.
К общей шине (ОШ) подключены
несколько абонентов, каждый из которых
функционирует автономно в
При необходимости связи арбитр вырабатывает общий для всех абонентов сигнал ВНИМАНИЕ и затем – АДРЕС нужного абонента. Этот абонент после идентификации своего адреса выдает в шину сигнал ГОТОВ либо ЗАНЯТ в зависимости от своего состояния. Получив сигнал готовности, арбитр сразу же формирует непрерывную многобайтную посылку – информационное сообщение (ИС), которое замыкается сигналом КОНЕЦ ПЕРЕДАЧИ. Приняв эту посылку, абонент отвечает сигналом КОНЕЦ ПРИЕМА при отсутствии ошибок передачи, либо сигналом ПОВТОРИТЬ ПЕРЕДАЧУ, если обнаружена ошибка. В последнем случае арбитр повторяет весь цикл связи заново.
Информационное сообщение имеет символьный характер. Каждый символ занимает 1 байт (8 разрядов). Алфавит сообщений содержит всего 200 символов. Остающиеся 56 символов могут быть использованы в качестве сигналов связи: ГОТОВ, ВНИМАНИЕ и др.
Для реализации связи каждому
абоненту придается интерфейсный модуль-контроллер
связи. Сигналы ГОТОВ и ПОВТОРИТЬ-
ВНИМАНИЕ |
217 |
11011001 |
АДРЕС |
57 |
00111001 |
ГОТОВ |
237 |
11101101 |
ЗАНЯТ |
253 |
11111101 |
КОНЕЦ_ПЕРЕДАЧИ |
114 |
01110000 |
КОНЕЦ_ПРИЕМА |
174 |
10101110 |
ПОВТОРИТЬ_ПЕРЕДАЧУ |
154 |
10100100 |
Схема микроконтроллера.
Для программирования необходимой логики работы мы будем использовать 3 из 8 выводов порта А и все 8 выводов порта B
Описание работы порта А
— На вывод 0 поступает сигнал синхронизации С1
— На вывод 1 поступает сигнал синхронизации С2
— Вывод 2 используется для посылки и приёма Арбитру управляющих сигналов («Внимание», «Готов» ит.д.), а также для приёма информационного сообщения.
Выводы 3-7 не используются и поэтому не показаны на схеме
Описание работы порта B
8 выводов порта B используются для параллельной передачи и приёма Абоненту управляющих сигналов («Ошибка передачи», «Конец работы» ит.д.), а также для пересылки информационного сообщения, которое идёт от Арбитра
В качестве программируемого микроконтроллера возьмём ATmega169. Выбор обусловлен тем, что данное устройство поддерживает необходимые для выполнения курсового проекта характеристики, хотя и является избыточным.
Работу программы будем проверять в эмуляторе AVR Studio 4.13.528
Компилировать программу будем в WinAVR 20071221
AVR Studio – интегрированная среда проектирования программ для микроконтроллеров, которую можно свободно скачать с сайта производителя www.atmel.com
WinAVR – программный пакет, содержащий
в себе интересующий нас компилятор GNU GCC для C. WinAVR
можно свободно скачать с сайта разработчиков http://sourceforge.net/
Для разбора задания установите сначала 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 можно следить за значениями переменных.
Приложение
/*
Подключение заголовочного файла io.h, который в свою очередь подключит iom169.h
iom169.h - заголовочный файл,
который ставит в соответствие
константам PORTA и PORTB реальные адреса
выводов конкретного
Таким образом io.h позволяет работать с портами ввода-вывода
*/
#include <avr/io.h>
// Подключение заголовочного
файла, который позволяет
#include <stdbool.h>
// Определение пользовательского типа данных byte
typedef unsigned char byte;
// Константы, определённые для обращения к выводам порта А
#define C1 (PINA & 0x01) /* 0-вой вывод порта А, на который приходит сигнал С1 */
#define C2 (PINA & 0x02) /* 1-вой вывод порта А, на который приходит сигнал С2 */
#define DATAIN ((PINA & 0x04) >> 2) /* 2-вой вывод порта А, на который приходит информация. Чтение информации из порта */
#define DATAOUT(x) PORTA = (PORTA & ~(0x04)) | (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)) | (DATAIN << C2Count); // считываем очередной бит с информационной линии
/*
(1 << C2Count) даст нам байт с единицой, установленной на том бите, который мы должны установить
~(1 << C2Count) инвертирование
даст нам байт с нулём,
(frameFromArbiter & ~(1 << C2Count)) даст нам исходный frameFromArbiter с нулём, установленным на том бите, который мы должны установить
DATAIN << C2Count) даст нам
бит со значением пришедшим
по информационной линии,
Итоговое поразрядное ИЛИ даст нам исходный frameFromArbiter со значением пришедшим по информационной линии, которое установится в frameFromArbiter на номере бита, равном номеру сигнала С2
*/
C2Count++; // Считаем номер пришёдшего сигнала С2
C2Out = false; // Запоминаем, что С2 пришёл, но ещё не уходил
}
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 = 0x00; // Указываем микроконтроллеру настроить все выводы на приём информации
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 SendToAbonentRequestAboutAbone
{
DDRB = 0xFF; // Указываем микроконтроллеру настроить все выводы порта B на вывод информации
SendFrameToAbonent(READY); // Посылаем байт ГОТОВ Абоненту
if(frameToAbonentWasSent) // Если байт был послан
{
requestToAbonentWasSent = true; // Запоминаем, что запрос Абоненту был послан
}
}
// Получаем от Абонента его состояние
void ReceiveFromAbonentAbonentState
{
DDRB = 0x00; // Указываем микроконтроллеру настроить все выводы порта 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 = 0x04;
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 ReceiveDataMessageFromArbiterA
{
DDRA = 0x00; // Указываем микроконтроллеру настроить все выводы на приём информации
ReceiveFrameFromArbiter(); // Получить байт от Арбитра
if(frameCameFromArbiter) // Если байт от АРбитра пришёл
{
SendFrameToAbonent(
frameCameFromArbiter = false; // Запоминаем, что мы обработали байт, пришедший от Арбитра
if(frameFromArbiter == END_OF_TRANSFER_SEQUENCE) // Если пришёдший байт совпадает с символом КОНЕЦ ПЕРЕДАЧИ
{
DataMessageRefered = true; // Запоминаем что информационное сообщение переслали
}
}
}
int main (void)
{
while(1) // Запускаем бесконечный цикл
{
if(!AddressCameFromArbiter) // Если адрес МК ещё не пришёл от Арбитра,
{
WaitAddressFromArbiter(); // ждём
}
if(AddressCameFromArbiter) // Если от Арбитра пришёл адрес МК
{
SendToAbonentRequestAboutAbone
if(requestToAbonentWasSent) // Если запрос
о состоянии Абонента был
{
ReceiveFromAbonentAbonentState
}
if(abonentStateReceived) // Если получили состояние Абонента,
{
if(abonentState == END_OF_WORK) // и состояние равно КОНЕЦ РАБОТЫ,
{
SendToArbiterAbonentState(
if(
{
ReceiveDataMessageFromArbiterA
if(DataMessageRefered) // Если информационное сообщение было отослано
{
SendToAbonentRequestAboutAbone
if(requestToAbonentWasSent) // Если запрос
о состоянии Абонента был
{
ReceiveFromAbonentAbonentState
Информация о работе Микроконтроллеры: от простого к сложному