Рефераты. Проектирование удаленного устройства индикации

Для такой схемы подходит включение транзистора, показанное на рис.3. Когда ключ открыт, транзистор находится в закрытом состоянии и на входы RESET AVR и RST LCD-дисплея поступает сигнал логической единицы. Когда ключ замыкается, транзистор открывается и на входы сброса устройств поступает сигнал логического нуля.

Рис.3 Схема формирования сигнала сброса


2.4 Схемы входных и выходных устройств


Входным устройством в нашем проекте является микросхема обеспечения связи по протоколу передачи данных RS-485 МАХ 485 со следующими электрическими характеристиками:

Из этих параметров видно, что микросхема МАХ485 согласуется с микроконтроллером ATmegal6.


Рис. 4 Подключение микросхемы MAX4S5


Выходное устройство жидкокристаллический графический дисплей BG12864D фирмы Bolymin со встроенным контроллером Т6963С. Этот дисплей обладает следующими характеристиками:

• Механические характеристики

• Назначение выводов

В соответствии с этими параметрами схема подключения LCD-дисплея к микроконтроллеру будет следующей:



2.5 Схема стабилизатора напряжения


В качестве стабилизатора напряжения в нашем устройстве используется импульсный понижающий стабилизатор LM2574, который обладает следующими характеристиками:

•   входное напряжение - до 60 V {для HV версий)

•   выходное напряжение - 3.3 V, 5 V, 12 V, 15V

•   выходной ток - 0.5 А

Схема включения стабилизатора для преобразования +10 V - +5 V приведена на рис.6:

Рис. 6 (Схема стабилизатора напряжения



3. Проектирование программного обеспечения микроконтроллера


3.1 Проектирование функции инициализации микроконтроллера


Процедура инициализации микроконтроллера должна состоять из процедур или операторов инициализации всех узлов самого микроконтроллера и всех периферийных устройств, и установить все начальные значения для их регистров. Таким образом, мы должны проинициализировать следующие узлы устройства - порт А, порт С, УСАПП, таймер 0 и LCD-дисплей.

Порты А и С в начале работы устройства работают только на вывод данных, поэтому при их настройке необходимо в соответствующие регистры DDRx записать значение 0, тем самым настроив все их выводы на передачу данных. Для этого используются две процедуры;


void InitPortAWrite(void){

DDRA = Oxff; }

void InitPortCWrite(void){ DDRC = Oxff; PORTC = 0x30;


Инициализация таймера О проходит по следующему алгоритму - устанавливается делитель частоты на 1024 записью значения 5 в регистр TCCRO. Затем разрешается прерывание этого таймера и устанавливается его начальное значение:


void InitTimer(void)

i

_disable_interrupt() ;

TCCRO = 5;// установить делитель частоты 1024

TIMSK |= (1 « TOIEO); // разрешить прерывания таймера

TCNTO = TmrO_Reload;

enable_interrupt{);

]


Инициализация УСАПП работает следующим образом - в регистр

UBRR записывается значение, которое соответствует заданной скорости передачи данных для соответствующей частоты работы микроконтроллера.

УСАПП и параметры кадра данных. Кроме этого, т.к. прием и обработка данных в программе происходит через кольцевой буфер, то в процедуре инициализации необходимо провести начальные установки для головы и хвост буфера - обнулить их.


void USART_Init( unsigned int baudrate )

i

unsigned char x;

UBRROH = (unsigned char) (baudrate»8) ; UBRROL = (unsigned char) baudrate;

UCSRB = (USARTJRxHead = x;


3.2 Проектирование процедур обработки прерываний


В процессе работы нашего устройства могут возникнуть два прерывания - от таймера 0 и от УСАПП. Прерывание от таймера О обрабатывается очень просто: перезагружается начальное значение и флаг его срабатывания устанавливается в 1.

pragma vector=TIMERO_OVF_vect

interrupt void TIMERO_OVF_interrupt(void)

{

TCNT0=TmrO_Reload; TmrOFlag = 1;

}


Прерывание от УСАПП говорит о том, что прием пакета данных был закончен и принят в буферный регистр UDR. Обработчик этого прерывания должен принять эти данные и поместить в кольцевой буфер. Для этого должен быть рассчитан новый индекс буфера (указатель головы) и если этот индекс вдруг стал равен указателю хвоста, это говорит о том, что произошла ошибка и буфер приемника переполнился.


^pragma vector=USART_RXC__vect

^interrupt void USART_RX_interrupt{ void )

{

unsigned char data; unsigned char tmphead;

data = UDR;

tmphead = ( USART_RxHead + 1 );

USART_RxHead = tmphead; /* Сохранить новый индекс V

if < tmphead == USART_RxTail )

(

/* Ошибка! Буффер приемника переполнен */

)

USART_RxBuf[tmphead] = data; /* Сохранить полученные данные в буффере */

}



3.3 Проектирование процедур ввода информации


Ввод информации в разрабатываемое устройство осуществляется через УСАПП по протоколу RS-4 85. Как уже отмечалось, прием данных в программе происходит по прерыванию от УСАПП, обработчик которого помещает принятый байт в Оуфер приемника. В главной программе, для того, чтобы можно было анализировать этот буфер и читать данные уже непосредственно из него, необходима процедура, которая будет доставать данные из буфера таким образом, чтобы первыми поступали байты, попавшие в буфер раньше всех. Это делает процедура USART_Receive(), которая сначала ждет поступления данных в буфер, а затем по одному байту достает их оттуда.


BYTE USART_Receive( void )

1

unsigned char tmptail;

while ( USARTJixHead == USART_RxTail )

;

tmptail = USART_RxTail + 1; USART_RxTail = tmptail; return USART_RxBuf[tmptail];

f


3.4 Проектирование процедур вывода информации


Вывод информации в нашем устройстве осуществляется на LCD-дисплей. Основной процедурой, которая отображает строки поступивших данных на дисплее - это процедура AutoWriteMode(), которая по сути управляет дисплеем, выводя на него последовательно символы, хранящиеся в глобальном массиве OutString[], в режиме автозаписи, При этом нам необходимо только менять адрес позиции, в которую выводятся данные.

WORD AutoWriteMode(WORD Address, BYTE NumBytes)

{

SetAddressPointer(Address); SendCommanct{SET_DATA_AUTO_HRITE_COMMAND);

forfint i = 0; i < NumBytes; i++) {

AutoWrite(OutString[i]);

Address++; }

SendCommand(AUTO_RESET_COMMAND); return Address; }


3.5 Проектирование процедур управления периферийными устройствами


Все процедуры управления LCD-дисплеем осуществляются согласно системе команд встроенного контроллера Т6963:



3.6 Проектирование процедуры main()


Процедура main{) работает следующим образом после инициализации все узлов AVR и периферийных устройств, разрешается выполнение всех прерываний. После этого программа ждет срабатывания таймера, который настроен таким образом, что он немного чаще, чем может происходить прерывание от УСАПП. Сигналом того, что таймер 0 сработал служит факт установки глобальной переменной TmrOFlag в 1, что делается обработчиком прерываний таймера.

Затем, все время, пока кольцевой буфер не будет пуст, происходит считывание данных из него. Считанный байт помещается в строку-массив OutString[], и увеличивается счетчик принятых байт.

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

В любом случае происходит сброс флага таймера в ноль и происходит ожидание следующего срабатывания таймера.



4. Листинг программы

Файл макроопределений my_header.h:


^define BYTE unsigned char ttdefine WORD unsigned int

ttdefine READ_STATUS_COMMAND 0x39

ttdefine DATA_WRITE_COMMAND 0x32

tfdefine COMMANDjmTE_COMMAND ОхЗА

// Установка регистров

^define SET_CURSOR_COMMAKD 0x21

tfdefine SET_OFFSET_COMMAND 0x22

#define SET_ADDRESS_COMMAND 0x24

// Установка контрольного слова

#define SET_TEXT_HOME_ADDRESS_COMMAND 0x^0

fldefine SET_TEXT_AREA_COMMAHD0x41

#define SET_GR№HIC_HOME_ADDRESS_CO№1AND 0x42

#define SET_GRAPHIC_AREA_CCMMAND0x43

// Константы установки режима

^define OR_MODE0x80

tfdefine EXOR_MODE0x81

^define ANDJMODE0x83

#define TEXT_ATTRIBUTE_MODE0x84

^define INTERNAL_CG_ROM_MODE 0x80

tfdefine EXTERNAL_CG_RAM__MODE 0x88

// Константы режима дисплея

#define DISPLAY_OFF0x90

^define CURSOR_ON_BLIHK_OFF0x92

^define CURSOR_ON_BLINK_OK0x93

#define TEXT_ON_GRAPHIC_OFF0x94

#define TEXT__OFF_GRAPHIC_ON0x98

^define TEXT_ON_GRAPHIC_OnOX9C

// Размер курсора

#define ONE_LINE OxAO

tfdefine TWO_LINE OxAl

^define THREE_LINEOxA2

ttdefine FOUR_LINE ОхАЗ

^define FIVE_LINE OxA4

^define SIX_LINE OxA5

^define SEVEN_LINEOxA6

^define EIGHT_LINEOxA7

// Автоматическое чтение/данных

tfdefine SET_DATA_AUTO_WRITE_COMMAND OxBO

^define SET_DATA_AUTO_READ_COMMAND OxBl

^define AUTO_RESET_COMMANDOxB2

//

#define SCREEN_PEEK_CCMMANDOxEO

#define SCREEN_COPY_CC»1MANDOxE8

// Установка/сброс Оитов

tfdefine SET_BIT OxFO

^define RESET_BIT OxF8

^define BIT_0 OxFO

#define BIT_1 OxFl

ttdefine BIT_2 OxF2

^define BIT_3 OxF3

idefine BIT_4 OxF4

#define BIT_5 OxFS

^define BIT_6 OxF6

^define BIT_7OxF7

Файл главкой программы kurs.c;

/* Includes */ ^include <iom!28.h> ^include <ina90.h>

Sinclude "my_header.h"

^define USART_RX_BUFFER_SI2E 128

itdefine TmrOReload 4

static unsigned char TmrOFlag;

Static unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE];

static volatile unsigned char USART_RxHead; static volatile unsigned char USART_RxTail;

static BYTE OutString[128];

// Процедуры инициализации устройств

void InitAVR(void);

void USART_Init( unsigned int baudrate );

void InitLCD(void);

void InitTimer(void);

void InitPortARead(void);

void InitPortAWrite(void)?

void InitPortCWrite(void);

// Процедуры для работы с УСАПП и LCD

unsigned char USART_Receive( void );

void Data«rite<BYTE Data);

void CommandWrite(BYTE Command);

void ReadStatus(void);

void ReadStatus2(void);

void SendCoimand{BYTE Command);

void SendlByteCommand(BYTE Data, BYTE Command);

void Send2ByteCommand(WORD Data, BYTE Command);

void SetCursorPointer(WORD Position)

void SetAddressPointer(WORD Address)

void ByteWriteToRam(WORD AddressPointer, BYTE Data)

void AutoWrite(BYTE Data);

void mainf void )

f

BYTE HumBytes = 0;

InitAVR();

_SEI(); /* Разрешить прерывания */

while (!)

{

if(TmrOFlag) // Произошло срабатывание таймера

{

BYTE rec = 0;

while(DatalnReceiveBuffer() != 0) // Пока буффер не пуст

{

rec = USART_Receive(); // Приняли байт из буффера

OutString[NumBytes] = Rebuild(rec); // Записали его в строку NumBytes-n-;// Увеличить счетчик принятых байт

if (rec == OxOD)// Конец строки - ?

f

/* Выводим строку на LCD в режиме AutoWrite*/

AutoWriteModefO, —NumBytes)

for(int i = 0; i <= NumBytes; i++) OutStringU] = 0;

NumBytes = 0; }

\

TmrOFlag = 0;

} )

}

/* Процедура инициализации USART */ void USART_Init( unsigned int baudrate ) t

unsigned char x;

/* Установить частоту */

UBRROH = (unsigned char) (baudrate»8) ;

UBRROL = (unsigned char) baudrate;

/* Включить приемник UART */ UCSRB =

/* Процедура чтения из приемника */ BYTE USART_Receive( void

{

unsigned char tmptail;

while ( USART_RxHead == USART_RxTail ) /* Ждем поступления данных */ ;

tmptail = USART_RxTail + 1; /* Рассчет индекса буффера */ USART_RxTail = tmptail;/* Сохранить новели индекс */

return USART_RxBuf[tmptail]; /* Вернуть данные */

unsigned char DatalnReceiveBuffer( void )

{

return ( USART_RxHead != USART_RxTail ); /* Возвращает О если буффер пуст */

}

/* Обработчик прерывания от приемника */ #pragma vector=USART_RXC_vect _interrupt void USART_RX_interrupt( void ) {

unsigned char data;

unsigned char tmphead;

/* Прочесть полученные данные */

data = UDR;

/* Рассчет нового индекса */

tmphead = ( USARTJRxHead + 1 };

USART_RxHead = tmphead; /* Сохранить новый индекс V

if ( tmphead == USART_RxTail ) (

/* Ошибка! Буффер приемника переполнен */

}

USART_RxBuf[tmphead] = data; /* Сохранить полученные данные в буффере */ }

// Процедура инициализации таймера

void JnitTimer(void)

disable_interrupt();

;

}

/* Обработчик прерывания от таймера */ tfpragma vector=TIMERO_OVF_vect

interrupt void TIMERO_OVF_interrupt(void)

(

TCNTO=TmrO_Reload;

TmrOFlag =1; }

void InitPortARead(void) {

DDRA = 0;

PORTA = Oxff; }

void InitPortAWrite(void) {

DDRA = Oxff; }

void InitPortCWrite(void) I

DDRC = Oxff;

PORTC = 0x30; }

void InitLCD(void) {

int tmp = 0;

Send2ByteComraand(tm.p, ET_TEXT_HOME_ADDRESS_COMMAND);

tmp = 0x14;

Send2ByteCommand(tmp, SET_TEXT_AREA_COMMAND);

tmp = 0x80;

CoromandWrite(INTERNAL_CG_ROM_MODE);

CommandWrite{TEXT_ON_GRAPHIC_OFF);

I

void InitAVR(void)

I

InitPortAWriteO ;

InitPortCWriteO ;

InitLCDO;

InitTimer();

USART_Init( 47 };//Установить частоту 9,600 используя 1.3728MHz кристалл

}

// Процедуры для работы с LCD-дисплеем void DataWrite(BYTE Data)

t

PINC = DATA_WRITE_COMMAND;

PIНА ~ Data; }

void CommandWrite(BYTE Command)

f

PINC = CCMMRND_WRITE_COMMAND;

Р1ЫА = Command; J

void ReadStatus(void) {

BYTE tempFlag = 0; BYTE stat; InitPortAReadO ; while(tempFlag != 1) (

PINC = READ_STATUS_COMMAND;

Stat = PIMH.;

if((stat & 0x03) == 0x03) tempFlag = 1; }

InitPortAWriteO }

void ReadStatusS(void)

{

BYTE tempFlag = 0; BYTE stat; InitPortAReadO; while(tempFlag != 1) {

PINC = READ_STATUS_COMMAND;

stat = PINA;

if((stat b 0x08) == 0x08) tempFlag = 1; }

InitPortAWriteO }

void SendCommandfBYTE Command)

i

ReadStatus{); WriteCommand(Command); }

void SendlByteCommandfBYTE Data, BYTE Command) {

ReadStatus();

DataWrite(Data);

ReadStatus{);

CommandWrite(Command); }

void Send2ByteCommand{WORD Data, BYTE Command) {

ReadStatus();

DataWrite((BYTE)Data);

ReadStatus();

DataHrite((BYTE)(Data » 8));

ReadStatus ();

CommandWrite(Command); }

// Position: младший байт - координата X (от OOh до 4Fh)

//старший байт - координата Y (от OOh до IFh)

void SetCursorPointer(WORD Position)

{

Send2ByteComnand(Positon, SET_CURSOR_COMMAND);

// Address: младший байт

//старший байт

void SetAddressPointer(WORD Address)

{

Serid2BytesCommand[Address, S£T_ADDRESS_COMMAND);

}

void ByteWriteToRamfWORD AddressPointer, BYTE Data)

(

SetAddressPointer(AddressPointer);

ReadStatus();

DataWrite (Data) ,-

ReadStatus();

DataWrite(DATAJWRITEjLNC_ADP); }

void AutoWrite(BYTE Data) (

ReadStatus2();

PINA = Data;

}

// Массив символов OutString должен быть объявлен как

// глобальный массив типа BYTE

WORD AutoWriteModefWORD Address, BYTE NumBytes)

I

SetAddressPointer(Address);

SendCommand(SET_DATA_AUTO_WRITE_COMMRND);

for(int i = 0; i < NumBytes; i++) {

AutoWrite(OutString[i]);

Address++; }

SendCommand (AUTO_RESET_CCMMAND) ; return Address;

}







Страницы: 1, 2



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.