Микроконтроллеры: от простого к сложному

Автор работы: Пользователь скрыл имя, 22 Февраля 2014 в 20:21, курсовая работа

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

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

Содержание работы

Задание……………………………………………………………………….3
Схема микроконтроллера…………………………………………………...4
Описание работы………………………………………………………...…..4
Создание проекта в AVR Studio…………………………………………….5
Приложение………………………………………………………………….6
Список использованной литературы………………………………………13

Файлы: 1 файл

Курсовик Мой.docx

— 70.15 Кб (Скачать файл)

 

Задание……………………………………………………………………….3

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

Описание работы………………………………………………………...…..4

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

Приложение………………………………………………………………….6

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Задание.

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

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

Информационное сообщение  имеет символьный характер. Каждый символ занимает 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/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 можно следить за значениями переменных.

 

 

 

 

Приложение

/*

Подключение заголовочного  файла 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 & 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 SendToAbonentRequestAboutAbonentState()

{

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 ReceiveDataMessageFromArbiterAndReferToAbonent()

{

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

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(); // ждём  ответ

Информация о работе Микроконтроллеры: от простого к сложному