Обсуждаем контроллеры компании Atmel.
Ответить

Не отключается светодиод

Пн авг 08, 2022 10:51:39

Здравствуйте. После отправки команды через терминал включается определенный светодиод. Это работает. Он должен отключаться через 0,5 секунд. Но у меня не получается это реализовать. Никак не соображу.
Основной файл:

Спойлер
Код:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "matrix.h"
//*** Пример работы с USART интерфейсом микроконтроллеров AVR ***
#define BAUDRATE 9600 // Скорость обмена данными
#define F_CPU 8000000UL // Рабочая частота контроллера

volatile unsigned char NUM = 0;
unsigned char count = 0;
unsigned char byte_receive = 0;
unsigned char i = 1;

// Функция задержки в мкс
void PAUSE_us(unsigned char time_us)
{
    register unsigned char i;

    for(i = 0; i < time_us; i++)
    {
        asm volatile(" PUSH  R0 ");
        asm volatile(" POP   R0 ");
    }
}

// Функция задержки в мс
void PAUSE_ms(unsigned int time_ms)
{
    register unsigned int i;

    for(i = 0; i < time_ms; i++)
    {
        PAUSE_us(250);
        PAUSE_us(250);
        PAUSE_us(250);
        PAUSE_us(250);
    }
}

#define RS PD2
#define EN PD3

// Функция передачи команды
void lcd_com(unsigned char p)
{
    PORTA &= ~(1 << RS); // RS = 0 (запись команд)
    PORTA |= (1 << EN); // EN = 1 (начало записи команды в LCD)
    PORTA &= 0x0F;
    PORTA |= (p & 0xF0); // старший нибл
    PAUSE_us(100);
    PORTA &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    PAUSE_us(100);
    PORTA |= (1 << EN); // EN = 1 (начало записи команды в LCD)
    PORTA &= 0x0F;
    PORTA |= (p << 4); // младший нибл
    PAUSE_us(100);
    PORTA &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    PAUSE_us(100);
}

// Функция передачи данных
void lcd_data(unsigned char p)
{
    PORTA |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD)
    PORTA &= 0x0F;
    PORTA |= (p & 0xF0); // старший нибл
    PAUSE_us(100);
    PORTA &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    PAUSE_us(100);
    PORTA |= (1 << EN); // EN = 1 (начало записи команды в LCD)
    PORTA &= 0x0F;
    PORTA |= (p << 4); // младший нибл
    PAUSE_us(100);
    PORTA &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    PAUSE_us(100);
}

// Функция инициализации LCD
void lcd_init(void)
{
    PAUSE_ms(50); // Ожидание готовности ЖК-модуля

// Конфигурирование четырехразрядного режима
    PORTA |= (1 << PD5);
    PORTA &= ~(1 << PD4);

// Активизация четырехразрядного режима
    PORTA |= (1 << EN);
    PORTA &= ~(1 << EN);
    PAUSE_ms(5);

    lcd_com(0x28); // шина 4 бит, LCD - 2 строки
    lcd_com(0x08); // полное выключение дисплея
    lcd_com(0x01); // очистка дисплея
    PAUSE_us(100);
    lcd_com(0x06); // сдвиг курсора вправо
    lcd_com(0x0C); // включение дисплея, курсор не видим
}

// Функция вывода строки на LCD
void lcd_string(unsigned char command, char *string)
{
    lcd_com(0x0C);
    lcd_com(command);
    while(*string != '\0')
    {
        lcd_data(*string);
        string++;
    }
}

// Функция передачи данных по USART
void uart_send(char data)
{
    while(!( UCSRA & (1 << UDRE)));   // Ожидаем когда очистится буфер передачи
    UDR = data; // Помещаем данные в буфер, начинаем передачу
}

// Функция передачи строки по USART
void str_uart_send(char *string)
{
    while(*string != '\0')
    {
        uart_send(*string);
        string++;
    }
}

// Функция приема данных по USART
int uart_receive(void)
{
    while(!(UCSRA & (1 << RXC))); // Ожидаем, когда данные будут получены
    return UDR; // Читаем данные из буфера и возвращаем их при выходе из подпрограммы
}

// Функция инициализации USART
void uart_init(void)
{
// Параметры соединения: 8 бит данные, 1 стоповый бит, нет контроля четности
// USART Приемник: Включен
// USART Передатчик: Включен
// USART Режим: Асинхронный
// USART Скорость обмена: 9600

    UBRRL = (F_CPU/BAUDRATE/16-1); // Вычисляем скорость обмена данными
    UBRRH = (F_CPU/BAUDRATE/16-1) >> 8;

    UCSRB |= (1 << RXCIE)| // Разрешаем прерывание по завершению приема данных
             (1 << RXEN)|(1 << TXEN); // Включаем приемник и передатчик

    UCSRC |= (1 << URSEL)| // Для доступа к регистру UCSRC выставляем бит URSEL
             (1 << UCSZ1)|(1 << UCSZ0); // Размер посылки в кадре 8 бит
}

// Прерывание по окончанию приема данных по USART
ISR(USART_RXC_vect)
{
    NUM = UDR; // Принимаем символ по USART
    byte_receive = 1;
    uart_send(NUM); // Посылаем символ по USART

    if(NUM == 'a') // Если принят символ "a", включаем светодиод
        PORTB |= (1 << PB0);
    if(NUM == 'b') // Если принят символ "b", выключаем светодиод
        PORTB &= ~(1 << PB0);
}

// Главная функция
int main(void)
{

    DDRC=0xFF;
    DDRB=0xFF;
    PORTC=0x00;
    PORTB=0x00;

    DDRA  = 0b11111110;
    PORTA = 0x00;

    DDRD  = 0b11111110;
    PORTD = 0x00;

    lcd_init(); // Инициализация LCD
    uart_init(); // Инициализация USART

    sei(); // Глобально разрешаем прерывания

    str_uart_send("Initialization system\r\n"); // Передаем строку по USART
    lcd_string(0x80, " AVR USART TEST "); // Выводим строку на LCD
    PAUSE_ms(2500);
    lcd_com(0x01); // Очищаем LCD




    while(1)
    {
//char k='2';
        switch(NUM)
        {

        case '1':
            TOT();
            break;
        case '2':
            TIM();
            break;
        case '3':
            DAY();
            break;
        case '4':
            MTH();
            break;
        case '5':
            RES();
            break;
        case '6':
            COU();
            break;
        case '7':
            c100();
            break;
        case '8':
            c400();
            break;
        case '9':
            c700();
            break;
        case '0':
            BRK();
            break;
        case 'A':
            LF();
            break;
        case 'B':
            c200();
            break;
        case 'C':
            c500();
            break;
        case 'D':
            c800();
            break;
        case 'E':
            c000();
            break;
        case 'F':
            RF();
            break;
        case 'G':
            c300();
            break;
        case 'I':
            c600();
            break;
        case 'K':
            c900();
            break;
        case 'L':
            OK();
            break;

            //default: PORTA=0x00; PORTB=0x00;

        }

        if(byte_receive)
        {
            byte_receive = 0;
            count++;
            lcd_data(NUM); // Выводим символ на LCD
            if(count > 16) // Если строка заполнена
            {
                count = 0;
                lcd_com(0x01); // Очищаем LCD
            }
        }
    }
}



файл matrix:
Спойлер
Код:
#define ROW PORTC
#define COLUMN PORTB

char a[9]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00};
char b[9]= {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x00};



char c100()
{
    ROW=a[1];
    COLUMN=b[1];
 
    return 0;
}
char c200()  //200
{
    ROW=a[1];
    COLUMN=b[2];
   
    return 0;
}
char c300()  //300
{
    ROW=a[1];
    COLUMN=b[3];
   
    return 0;
}
char c400()  //400
{
    ROW=a[2];
    COLUMN=b[1];
   
    return 0;
}
char c500()  //500
{
    ROW=a[2];
    COLUMN=b[2];
     
    return 0;
}
char c600()  //600
{
    ROW=a[2];
    COLUMN=b[3];
   
    return 0;
}
char c700()  //700
{
    ROW=a[3];
    COLUMN=b[1];
       
    return 0;
}
char c800()  //800
{
    ROW=a[3];
    COLUMN=b[2];
       
    return 0;
}
char c900()  //900
{
    ROW=a[3];
    COLUMN=b[3];
       
    return 0;
}
char c000()  //000
{
    ROW=a[4];
    COLUMN=b[2];
         
    return 0;
}
char TOT()  //TOT
{
    ROW=a[0];
    COLUMN=b[0];
     
    return 0;
}
char TIM()  //TIM
{
    ROW=a[1];
    COLUMN=b[0];
       
    return 0;
}
char DAY()  //TIM
{
    ROW=a[2];
    COLUMN=b[0];
         
    return 0;
}
char MTH()  //TIM
{
    ROW=a[3];
    COLUMN=b[0];
     
    return 0;
}
char RES()  //TIM
{
    ROW=a[4];
    COLUMN=b[0];
     
    return 0;
}
char COU()  //TIM
{
    ROW=a[0];
    COLUMN=b[1];
       
    return 0;
}
char BRK()  //TIM
{
    ROW=a[4];
    COLUMN=b[1];
         
    return 0;
}
char LF()  //TIM
{
    ROW=a[0];
    COLUMN=b[2];
         
    return 0;
}
char RF()  //TIM
{
    ROW=a[0];
    COLUMN=b[3];
         
    return 0;
}
char OK()  //TIM
{
    ROW=a[4];
    COLUMN=b[3];
         
    return 0;
}


Изображение
Последний раз редактировалось azerhud Пн авг 08, 2022 15:25:46, всего редактировалось 1 раз.

Re: Не отключается светодиод

Пн авг 08, 2022 12:30:53

Азер, отступы, оформление... вам такие слова знакомы?
определения - DEFINE_STYLE
функции - camelStyle
переменные - snake_style...
NUM должно быть volatile unsigned char num;
Заводите счётчик. В лупе вставляете delay(1), при включении светодиода заряжаете счётчик, а в лупе его вычитаете, пока не обнулится, тогда и выключаете светодиод.
Ответить