Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

4 лаба микроконтроллеры

.docx
Скачиваний:
0
Добавлен:
25.11.2025
Размер:
435.54 Кб
Скачать

Министерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования «Омский государственный технический университет» Кафедра” Автоматизация и робототехника”

Лабораторная работа №4

По теме: «Программирование порта ввода-вывода с семисегментным индикатором в параллельном режиме подключения»

Вариант 13

Выполнил:

Студент группы АТП-222

Пискунов А.И.

Проверил:

Асс. Холмов М.А.

Омск 2025

Цель: Обеспечьте вывод значений из предыдущей лабораторной работы в режиме бегущей строки на четырех семисегментных индикаторах.

Теоретическая справка

Для формирования отдельного символа на семисегментном индикаторе необходимо семь информационных проводов (или восемь, для светодиода dp). При этом, если индикаторов два, то требуется уже 14 (16) проводов, для трех индикаторов – 21 (23), а для четырех – 28 (32). Но на демонстрационной плате семисегментных индикаторов их всего шестнадцать, а согласно таблице распиновки разъема используются всего 13 контактов. Индикатор CC56-12SRWA имеет внутреннюю структуру, представленную на рис. 1

Рисунок 1 – Индикатор CC56-12SRWA

Рисунок 2 – Электрическая схема платы индикатора

После подачи на вывод DIGX значения «лог 1» открывается соответствующий транзистор, и семисегментный индикатор данного разряда начинает отображать значение, установленное на выводах a-g, dp. С переключением «лог 1» с одного вывода DIGX на другой переключается и индикация с одного индикатора на другой. Эффект непрерывности возникает, когда индикаторы перемигиваются с частотой, превышающей инерционность человеческого зрения (25 кадров в секунду). Для комфортного восприятия требуется порядка 5 мс на один разряд, что в пересчете на четыре разряда составит время 20 мс. Такая задержка соответствует частоте 50 кадров в секунду (что в два раза больше минимально необходимой).

Так как расчет паузы между выводом значения на разряды не должен приводить к загрузке процессора, его организуют при помощи таймера, который обеспечивает выполнение вывода значения на очередной разряд динамической индикации через каждые 5 мс. После выполнения подпрограммы обработчика таймера процессор имеет возможность заниматься своей «основной» деятельностью.

С информацией о регистрах управления таймерами для используемых процессоров необходимо ознакомиться в официальной документации. Последовательность действий процессора для обеспечения динамической индикации в общем случае выглядит следующим образом:

− отключение индицируемого разряда;

− выбор нового разряда для индикации;

− расчет значения для отображения на новом разряде;

− выставление кода символа для нового разряда;

− выставление сигнала включения нового разряда.

Ход работы

Рисунок 1 – Алгоритм работы

Описание алгоритма:

  1. Установка частоты микроконтроллера

  2. Инициализация необходимых библиотек

  3. Инициализация переменных timer228, nomer и opa

  4. Инициализация массива для вывода на семи сегментный дисплей

  5. Порты PB0-3 устанавливаем, как выходы для дисплеев

  6. Выключаем их

  7. Отключение глобальных прерываний

  8. Обнуление регистра TCCR1A и TCCR1B

  9. Установка предделителя таймера на 64

  10. Устанавливаем значение сравнения, после которого сработает прерывание

  11. Разрешение прерывания по переполнению таймера

  12. Включение глобальных прерываний

  13. Все порты D устанавливаем, как выходы для сегментов a-f, а также устанавливаем им низкий уровень

  14. Начинается главный цикл

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

  16. Если переменная больше или равно 4, то приравнивается к 0

  17. Условие, проверяющее чему равна переменная timer228, которая отвечает за то символ должен показываться сейчас

  18. Если переменная равна или больше 7, то приравнивается к 0

  19. Условие, проверяющие равна переменная opa переменной nomer

  20. Если переменная opa не равна nomer, то значит, необходимо менять символ. Соответственно opa приравнивается к nomer, чтобы символ бесконечно не менялся пока находится в цикле, а лишь при прерывании

  21. Timer228 увеличивается на 1

  22. Меняется символ в зависимости от timer228

  23. Конец основного цикла

  24. Вход в обработчик прерывания при переполнении таймера.

  25. Вновь устанавливаем значение сравнения

  26. Условие, проверяющее чему равна переменная nomer

  27. Если переменная равна 0, то включается четвёртый дисплей, а остальные выключаются

  28. Условие, проверяющее чему равна переменная nomer

  29. Если переменная равна 1, то включается третий дисплей, а остальные выключаются

  30. Условие, проверяющее чему равна переменная nomer

  31. Если переменная равна 2, то включается второй дисплей, а остальные выключаются

  32. Условие, проверяющее чему равна переменная nomer

  33. Если переменная равна 3, то включается первый дисплей, а остальные выключаются

  34. Переменная nomer увеличивается на единицу

Листинг кода

#define F_CPU 16000000UL

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

int timer228=0;

int nomer=0;

int opa=0;

unsigned char number[] = {

0b1111111, // 8

0b0000110, // 1

0b1110001, // F

0b1100110, // 4

0b1110111, // A

0b1000000, // -

0b0111001, // C

0b1011110, // d

};

int main(void) {

DDRB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3);

PORTB |=(1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3);

cli();

TCCR1A = 0;

TCCR1B = 0;

TCCR1B |= (1 << CS11)|(1 << CS10);

TCNT1=53036;

TIMSK1 = (1 << TOIE1);

sei();

DDRD = 0xff;

PORTD = 0x00;

while (1) {

if(nomer >=4){

nomer=0;

}

if(timer228>=7){

timer228=0;}

if(opa != nomer){

opa=nomer;

timer228++;

PORTD = number[timer228];}

}

}

ISR(TIMER1_OVF_vect)

{

TCNT1=53036;

if(nomer == 0){

PORTB &= ~(1<<PB3);

PORTB |=(1<<PB0)|(1<<PB1)|(1<<PB2);}

if(nomer == 1){

PORTB &= ~(1<<PB2);

PORTB |=(1<<PB0)|(1<<PB1)|(1<<PB3);}

if(nomer == 2){

PORTB &= ~(1<<PB1);

PORTB |=(1<<PB0)|(1<<PB2)|(1<<PB3);}

if(nomer == 3){

PORTB &= ~(1<<PB0);

PORTB |=(1<<PB1)|(1<<PB2)|(1<<PB3);}

nomer++;

}

Рисунок 1 – Пример работы программы

Рисунок 2 – Пример работы программы

Рисунок 3 – Пример работы программы

Рисунок 4 – Пример работы программы

Вывод: в ходе выполнения работы была разработана программа для микроконтроллера AVR, обеспечивающую бегущую строку на четырёх семисегментных дисплеях