Djangirov1 / Vfrc3
.doc
Тема: Вывод информации с различных устройств
Цель работы: научиться осуществлять ввод информации с различных устройств с помощью микроконтроллера
Задание №1: Реализовать на микроконтроллере программу вывода на устройство отображения следующих символов и знаков, считанных с пользовательского пульта. Проверить работу программы в Proteus VSM.
При нажатии кнопки 1 – 1A2, при нажатии кнопки 2 – 2B3, при нажатии кнопки 3 – 3C4, при нажатии кнопки 4 – 4L5, при нажатии кнопки 5 – 5M6, при нажатии кнопки 6 – 6P7, при нажатии кнопки 7 – 7Y8, при нажатии кнопки 8 – 8Z9, при нажатии кнопки 9 – 9J0, при нажатии кнопки 0 – 0G1, при нажатии кнопки # – #, при нажатии кнопки * – *. Вывод на виртуальный терминал.
Код пограммы:
#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#define FOSC 11059200 // частота кварца
#define BAUD 9600 // скорость передачи данных
#define USART_UBBR_VALUE (FOSC/16/BAUD)-1 // значение, которое необходимо записать в UBRR чтобы получить требуемую скорость передачи
void USART_Init(void);
uint8_t USART_vReceiveByte(FILE *stream);
void USART_vSendByte(uint8_t u8Data, FILE *stream);
// Создаем поток для ввода/вывода на/с UART для использования стандартных
// функции ввод/вывода
FILE uart_file=FDEV_SETUP_STREAM(USART_vSendByte, USART_vReceiveByte,_FDEV_SETUP_RW); // поток доступен для чтения и записи
void USART_Init(void)
{ // установить скорость передачи данных
UBRRH=(uint8_t)((USART_UBBR_VALUE)>>8);
UBRRL=(uint8_t)(USART_UBBR_VALUE);
// Установить формат кадра - 8 бит, нет проверки четности, 1 стоп бит
UCSRC = (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
// Включить передатчик и приемник
UCSRB = (1<<RXEN)|(1<<TXEN);
UBRRH=(uint8_t)((USART_UBBR_VALUE)>>8);
}
void USART_vSendByte(uint8_t u8Data, FILE *stream)
{
// подождать пока передастся прошлый бит
while((UCSRA&(1<<UDRE)) == 0);
// передать данные
UDR = u8Data;
}
uint8_t USART_vReceiveByte(FILE *stream)
{
// Подождать пока осуществиться прием байта
while((UCSRA&(1<<RXC)) == 0);
// возвратить принятые данные
return UDR;
}
int main( void )
{
stdout=stdin=&uart_file; // указываем, что стандартные потоки должны ссылаться на созданный поток
uint8_t i=0; // счетчик цикла
DDRD=0b11111110; // устанавливаем первый вывод порта D на ввод, остальные на вывод
//(первый вывод служит для приема данных с USART, второй – для передачи)
char* str; // выводимая строка
USART_Init(); // инициализация USART
DDRC=0b11110001;
int k,z,j,pointer;
int OUT[]={0b11100001,0b11010001,0b10110001,0b01110001};
char* keyboard[4][3]={{"1A2","2B3","3C4"},
{"4L5","5M6","6P7"},
{"7Y8","8Z9","9J0"},
{"*","0G1","#"}};
while (1)
{
pointer=0;
z=4; j=4;
for (k=0; k<4; k++)
{
PORTC=OUT[k];
if ((PINC&0b00000010)==0) {z=k; j=2; pointer=1; goto label;}
if ((PINC&0b00000100)==0) {z=k; j=1; pointer=1; goto label;}
if ((PINC&0b00001000)==0) {z=k; j=0; pointer=1; goto label;}
}
label:
while ((PINC&0b00001110)!=0b00001110 && pointer==1){_delay_us(40);}//пока не замкнута ни одна кнопка
if (pointer==1)
{
str=keyboard[z][j];
printf("%s\n\r", str);
}
}
return 0;
}
Принтскрин работы:
Задание №2: Датчик температуры TC1047A. Предусмотреть усиление сигнала с датчика. Данные на устройстве отображения должны совпадать с показаниями вольтметра. ЖКИ дисплей.
Код программы:
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
#define lcd PORTB
#define rs PD0
#define rw PD1
#define en PD2
void adc_init(void);//настройка ацп
unsigned int adc_read(void);//чтение ацп
void adc_conversion(double);//преобразование ацп
void lcd_init(void);
void lcdcmd(unsigned char);
void lcddata(unsigned char);
uint16_t adc_out;
int main()
{
unsigned char data[12]= "ADC OUTPUT:";
int i=0;
DDRD=0x07;//пины для управления ЖКИ на вывод
DDRB=0xFF;//порт на вывод
DDRC=0xFF;//порт на вывод
lcd_init();
while(data[i]!='\0')
{
lcddata(data[i]);
_delay_ms(5);
i++;
}
adc_init();
/* Configure timer0*/
TCCR0=(5<<CS00); //установка делителя 1024
TIMSK=(1<<TOIE0); //при переполнении таймера/счётчика0 вызывается прерывание по вектору $012
sei();//ручная установка в 1 бита глобального разрешения прерываний регистра SREG
while(1);
}
void adc_init() // ADC configuration
{
ADMUX=(1<<REFS0); //Источник опорного питания - напряжение питания AVCC
ADCSRA=(1<<ADEN)|(7<<ADPS0)|(1<<ADSC)|(1<<ADIE)|(1<<ADATE);//настройка управляющего регистра; ADEN - разрешение АЦП; ADSC - запуск преобразования; ADATE - выбор режима работы АЦП; ADIE - разрешение прерывания от компаратора; ADPS0 - выбор частоты преобразования(7<<ADPS0 - предделитель частоты = 128)
SFIOR=(4<<ADTS0);//устанавливаем прерывание по срабатыванию таймера/счётчика0
}
ISR(ADC_vect) //обработка прерывания от АЦП
{
adc_conversion((ADC));
}
ISR(TIMER0_OVF_vect) //обработка прерывания по переполнению таймера/счётчика 0
{
}
/* this function is written to convert integer value to their corresponding ASCII value*/
void adc_conversion(double adc_out)
{
unsigned int adc_out1;
int i=0;
char position=0xC3;
adc_out /= 2.05;
for(i=0;i<=3;i++)
{
adc_out1=(uint16_t)adc_out%10;
adc_out=adc_out/10;
lcdcmd(position);
lcddata(48+adc_out1);
position--;
}
}
void lcd_init() // function for LCD initialization
{
lcdcmd(0x38);
lcdcmd(0x0C);
lcdcmd(0x01);
lcdcmd(0x06);
lcdcmd(0x80);
}
void lcdcmd(unsigned char cmdout)
{
lcd=cmdout;
PORTD=(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(10);
PORTD=(0<<rs)|(0<<rw)|(0<<en);
}
void lcddata(unsigned char dataout)
{
lcd=dataout;
PORTD=(1<<rs)|(0<<rw)|(1<<en);//rs 0 – регистр управления 1 - регистр данных
_delay_ms(10);
PORTD=(1<<rs)|(0<<rw)|(0<<en);// en – стробирующий импульс
}
Принтскрин работы:
Выводы: на этой лабораторной работе я научился осуществлять вывод информации, поступающих на МК с различных устройств – с матричной клавиатуры и от АЦП.