Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПУМУ КР 5 1Сем.docx
Скачиваний:
10
Добавлен:
30.03.2023
Размер:
48.27 Кб
Скачать

2 Управление таймер-счетчиками

Задание. Мигать попеременно светодиодами D1, D2 и D3. Время горения светодиода в два раза больше чем время простоя. При нажатии кнопки загораются D5 и D8. Организовать мигание с помощью прерываний от таймера..

Ниже приведен код, который будет управлять таймер-счетчикам микроконтроллера.

#include <xc.h>

#define _XTAL_FREQ 4000000

#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)

#pragma config WDTE = OFF // Watchdog Timer (WDT disabled)

#pragma config PWRTE = ON // Power-up Timer Enable bit (Power-up

//Timer is enabled)

#pragma config CP = OFF // Code Protection bit (Code protection disabled)

unsigned char result=1;

unsigned int TIM0_count=0;

void CheckButton(void)// ф-ция опроса кнопки

{

unsigned int butcount=0;

while(!RA2)

{

if(butcount < 10000)

{

butcount++;

}

else

{PORTB=0; // погашение всех светодиодов

TIM0_count=0;//сброс счетчика по таймеру, чтоб начать с начала

if (result == 0)result = 1; else result = 0;// изменение режима

/* переключение режима: result = 0 – мигают D5, D7, result = 1 – мигают D1, D2, D3 */

break;

}

}

}

void interrupt timer0()

{

if (result) // до нажатия кнопки

switch(TIM0_count/10) // пауза через 10 отсчётов таймера

{

case 0:

PORTBbits.RB1 = 1; // Вкл D1

break;

case 2:// не 1 а 2 10 отсчетов пропускаем – горит в 2 раза дольше

PORTBbits.RB1 = 0; // Выкл D1

break;

case 3:

PORTBbits.RB2 = 1; // Вкл D2

break;

case 5: // 10 отсчетов пропускаем – горит в 2 раза дольше

PORTBbits.RB2 = 0; // Выкл D2

break;

case 6:

PORTBbits.RB3 = 1; // аналогично

break;

case 8:

PORTBbits.RB3 = 0;

break;

case 9:

TIM0_count=0; /*сброс счетчика таймера после погасания D3 через 10 отсчетов*/

break;

}

if (!result) // после нажатия кнопки

switch(TIM0_count/10)

{

case 0:

PORTBbits.RB5 = 1; // Вкл D5

break;

case 2: // 10 отсчетов пропускаем – горит в 2 раза дольше

PORTBbits.RB5 = 0; // Выкл D2

break;

case 3:

PORTBbits.RB7 = 1;

break;

case 5: // 10 отсчетов пропускаем – горит в 2 раза дольше

PORTBbits.RB7 = 0;

break;

case 7:

TIM0_count=0; /*сброс счетчика таймера после погасания D3 через 10 отсчетов*/

break;

}

TIM0_count++;/*увеличение счетчика таймера */

T0IF=0;// сброс флага прерывания

}

void main(void) {

TRISB = 0x00; // Все выводы настраиваем порта B как выход

PORTB = 0x00; // гасим все светодиоды

TRISA &= ~0x03;// Порт А2 – на вход

PORTA &= ~0x03; /* подключен внутренний подтягивающий резистор на порт А2*/

OPTION_REG=0x07; /* включает биты 0,1 и 2 — это биты предделителя, используется деление частоты максимальное — на 256*/

INTCON=0xA0; /* включаются глобальные прерывания и прерывания от таймера, установкой в 1 биты 7 и 5 регистра INTCON*/

TMR0=0;/* заносится 0 в регистр счѐта таймера, тем самым запустится

таймер. */

while(1)

{CheckButton(); // опрос кнопки постоянно

}

return;

}

3 Управлять семисегментными индикаторами

Задание. Выполнить отсчет времени от 2500 до 1500, с шагом 50. Частота смены 1 Гц.

Ниже приведен код, который будет управлять сегментным индикатором.

#include <xc.h>

#define _XTAL_FREQ 4000000

// CONFIG

#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)

#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)

#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)

#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)

#pragma config LVP = OFF /* Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for

programming)*/

#pragma config CPD = OFF /*Data EEPROM Memory Code Protection bit

(Data EEPROM code protection off)*/

#pragma config WRT = OFF /* Flash Program Memory Write Enable bits

(Write protection off; all program memory may be written to by EECON control)*/

#pragma config CP = OFF /*Flash Program Memory Code Protection bit

(Code protection off)*/

//------------------------------------------------------------

unsigned int i=2500,j,k,digit[4],TIM0_count=0,upd=0; /* глобальные переменные*/

//--------------------------------------------------------------

void segchar (unsigned char seg) /* функция отображения цифр 0-9 на индикаторах*/

{

switch (seg)

{

case 1:

PORTD = ~0b11111001; //”1” – инвертированные значения из методички

break;

case 2:

PORTD = ~0b10100100;//”2”

break;

case 3:

PORTD = ~0b10110000;

break;

case 4:

PORTD = ~0b10011001;

break;

case 5:

PORTD = ~0b10010010;

break;

case 6:

PORTD = ~0b10000010;

break;

case 7:

PORTD = ~0b11111000;

break;

case 8:

PORTD = ~0b10000000;

break;

case 9:

PORTD = ~0b10010000;

break;

case 0:

PORTD = ~0b11000000;

break;

}

}

void interrupt timer0()

{j=i; k=0;

while(j>0) /* разделение числа i (2500…1500) на отдельные цифры в обратной последовательности*/

{

digit[k++] = j % 10;//заполнение массива с цифрами числа i

j = j / 10;

}

switch(TIM0_count/2) // проверка значения счетчика TIM0_count таймера

{

case 1: // вывод тысяч

PORTBbits.RB7 = 1;

segchar(digit[3]); /*из массива достаем цифру тысяч и отправляем ее не индикатор тысяч */

break;

case 2:// // вывод сотен

PORTBbits.RB7 = 0;

PORTBbits.RB6 = 1;

segchar(digit[2]);

break;

case 3: // вывод десятков

PORTBbits.RB6 = 0;

PORTBbits.RB5 = 1;

segchar(digit[1]);

break;

case 4: // вывод единиц

PORTBbits.RB5 = 0;

PORTBbits.RB4 = 1;

segchar(digit[0]);

break;

case 5: // сброс счетчика TIM0_count таймера

PORTBbits.RB4 =0; // выкл последней цифры - единицы

TIM0_count=0;

upd++; счетчик для увеличения i - Частота смены 1 Гц.

break;

}

if (upd==20){ i=i-50;upd=0;if(i<1500)i=2500;}// i=2500…1500

TIM0_count++;

}

//--------------------------------------------------------------

void main(void) {

TRISD = 0x00;

PORTD = 0xFF;

TRISB = 0x00;

PORTB = 0x80;

OPTION_REG=0x00; // Предделитель частоты таймера = 2, f =2 МГц

INTCON=0xA0; // прерывание по таймеру вкл

TMR0=0;

while(1){}// тут пусто, все в прерывании

}