Например TDA7294

Форум РадиоКот • Просмотр темы - Вопросы по С/С++ (СИ)
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Ср июл 16, 2025 07:56:53

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 7669 ]     ... , , , 243, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 14:27:36 
Прорезались зубы
Аватар пользователя

Карма: 4
Рейтинг сообщений: 27
Зарегистрирован: Чт янв 08, 2015 22:31:15
Сообщений: 247
Рейтинг сообщения: 0
Zhuk72, то есть получается так:
ISR (TIMER0_OVF_vect) заменяю на ISR (TIMER2_OVF_vect)

Обработчик прерывания по переполнению таймера вставляю перед главной программой int main (void)
ISR (TIMER2_OVF_vect)
{
LED_DIG_PORT |= (1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B); // Гасим все разряды
}

Настройки таймера такие
TCCR2 |= (1 << WGM21)|(1 << WGM20)|(1 << CS21); // Режим FASTPWM. Предделитель на 8
TIMSK |= (1 << TOIE2)|(1 << OCIE2); // Разрешение прерываний по таймеру 2
OCR2 = 50; // Начальное значение OCR2


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 15:03:25 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Пробуйте.

Но для сохранении идеологии вашего исходника сделайте такую поправку:
Код:
ISR (TIMER2_OVF_vect)
{
///////////////////////////////////
// Индикатор с общим анодом (ОА)
///////////////////////////////////
#ifndef LEDS_OK
    LED_DIG_PORT &= ~((1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B));
///////////////////////////////////
// Индикатор с общим катодом (ОК)
///////////////////////////////////
#else
    LED_DIG_PORT |= (1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B);
#endif
}

И для стройности вставьте после основного прерывания от таймера.

По поводу настроек таймера ничего не скажу. Это вы сами сравните с ДШ на МК.

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 20:03:55 
Прорезались зубы
Аватар пользователя

Карма: 4
Рейтинг сообщений: 27
Зарегистрирован: Чт янв 08, 2015 22:31:15
Сообщений: 247
Рейтинг сообщения: 0
Zhuk72, компилятор сыпет ошибками что не знает такого таймера. Полез в даташит, оказывается действительно у ATTiny261A нет такого таймера. Это получается что яркость семисегментного индикатора уменьшить программно не получиться на этом микроконтроллере?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 20:19:14 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Так с этого и надо было начинать, с чтения ДШ. Да и тип МК вы держали в секрете.
Если есть 2 таймера, то можно легко сделать. Да и с одним тоже с чуть большими движениями.

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Выбираем индустриальные и медицинские источники питания MEAN WELL в открытом исполнении

Использование модульных источников питания открытого типа широко распространено в современных устройствах. Присущие им компактность, гибкость в интеграции и высокая эффективность делают их отличным решением для систем промышленной автоматизации, телекоммуникационного оборудования, медицинской техники, устройств «умного дома» и прочих приложений. Рассмотрим подробнее характеристики и особенности трех самых популярных вариантов AC/DC-преобразователей MW открытого типа, подходящих для применения в промышленных устройствах - серий EPS, EPP и RPS представленных на Meanwell.market.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 20:31:13 
Прорезались зубы
Аватар пользователя

Карма: 4
Рейтинг сообщений: 27
Зарегистрирован: Чт янв 08, 2015 22:31:15
Сообщений: 247
Рейтинг сообщения: 0
Zhuk72, да я сам об этом как то сразу и не подумал. Оказалось зря.
А с теми таймерами которые есть у ATTiny261A не подскажите конструкцию?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 20:47:42 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Я атмелами не занимаюсь, поэтому надо дш смотреть.
С двумя таймерами принцип такой: в конце прерывания первого таймера заряжаете и запускаете второй таймер, а уже в прерывании второго отключаете индикатор и останавливаете таймер. Период второго таймера должен быть меньше, чем у первого. Чем он будет меньше, тем ниже яркость свечения индикатора.

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 20:59:16 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 98
Рейтинг сообщений: 2116
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18403
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
вы не учитываете, что у этой тиньки развитая система цифровых компараторов для таймеров. чтобы регулировать яркость при динамической индикации достаточно одного таймера, общий принцип я описывал здесь: http://arv.radioliga.com/content/view/101/49/

Добавлено after 2 minutes 58 seconds:
Электpониk писал(а):
Реализация изменения скважности импульсов показана тут http://radioparty.ru/prog-avr/program-c ... egment-avr

блин, такое ощущение, что статья была написана после прочтения моей :)

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт ноя 29, 2016 21:37:45 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
ARV писал(а):
вы не учитываете, что у этой тиньки развитая система цифровых компараторов для таймеров.

Потому и сказал, что не занимаюсь Атмелами :) Я описал общий случай, не привязанный к конкретному железу. Если можно обойтись одним таймером с компаратором - тем лучше.

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср ноя 30, 2016 11:31:00 
Прорезались зубы
Аватар пользователя

Карма: 4
Рейтинг сообщений: 27
Зарегистрирован: Чт янв 08, 2015 22:31:15
Сообщений: 247
Рейтинг сообщения: 0
Похоже что нужно юзать Timer1 у него есть Fast PWM Mode.
Цитата:
The fast Pulse Width Modulation or fast PWM mode (PWM1A/PWM1B = 1 and WGM1[1:0] = 00)
provides a high frequency PWM waveform generation option. The fast PWM differs from the
other PWM option by its single-slope operation. The counter counts from BOTTOM to TOP
(defined as OCR1C) then restarts from BOTTOM. In non-inverting Compare Output mode the
Waveform Output (OCW1x) is cleared on the Compare Match between TCNT1 and OCR1x and
set at BOTTOM. In inverting Compare Output mode, the Waveform Output is set on Compare
Match and cleared at BOTTOM. In complementary Compare Output mode the Waveform Output
is cleared on the Compare Match and set at BOTTOM.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср ноя 30, 2016 21:42:28 
Друг Кота
Аватар пользователя

Карма: 27
Рейтинг сообщений: 33
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Сообщений: 6296
Откуда: Ukraine
Рейтинг сообщения: 0
Электpониk, принцип прост как бублик и состоит в следующем
берете 8 разрядный таймер и настраиваете его на режим Fast PWM Mode
в прерывании по переполнению зажигаете нужный анод, нужного разряда и выводите цифру, а в сравнении весь этот зоопарк тушим :))
Код:

//----------
// Timer/Counter 2 initialization
// Clock source: System Clock
   TCCR2 = 1 << WGM21 | 1 << WGM20 | // FastPWM
                 1 << CS22;                // предделитель на 64 (16MHz/64/256/6 = 163Hz)
//                                                                                          163 -частота мигания одной лампы
//                                                                                       6 -количество ламп
//                                                                                        256 - 8-ми разрядний таймер 2^8=256
//                                                                                      64 - предделитель таймера
//                                                                                      16 - частота МК
   OCR2=250;
//----------
   TIMSK = 1 << OCIE2 | // Timer/Counter2 Output Compare Match Interrupt Enable
         1 << TOIE2;  // Timer/Counter2 Overflow Interrupt Enable
//----------



ISR (TIMER2_OVF_vect) {


   PORTB = Screen[var];      // выодим нужную цифру

   switch (var) {
          case 0: ANOD_RAZRYDA_0(); break; // анод един. секунд
          case 1: ANOD_RAZRYDA_1(); break; // анод дес.  секунд
          case 2: ANOD_RAZRYDA_2(); break; // анод един. минут
          case 3: ANOD_RAZRYDA_3(); break; // анод дес. минут
          case 4: ANOD_RAZRYDA_4(); break; // анод един. часов
          case 5: ANOD_RAZRYDA_5(); break; // анод дес. часов
          default:              break;
   }
}



   if (++var >= 5) var = 0;
   OCR2=br_razryda[var];



}


ISR (TIMER2_COMP_vect) {

   TURN_OFF_INDICATORS_AND_DOT();  // выключаем анодные драйвера (гасим индикаторы )
}




изменяя значение для OCR2 мы тем самым изменяем яркость определенного разряда
код для ATmega8

_________________
Tell Me The Truth


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пт дек 02, 2016 20:19:55 
Прорезались зубы
Аватар пользователя

Карма: 4
Рейтинг сообщений: 27
Зарегистрирован: Чт янв 08, 2015 22:31:15
Сообщений: 247
Рейтинг сообщения: 0
Принцип я понимаю. Вот только проблема в том, что у ATTINY261A нет Timer2. Но есть Timer1 с режимом FastPWM. Можно его задействовать. Правда, сложность в том, что у него несколько компараторов и куча разнообразных режимов и регистров. Ну не беда, после изучения даташита, стали понятны назначения регистров Timer1, и как их настраивать.
Переделал программу на Timer1, но проблема в том, что не срабатывает прерывание по сравнению вообще. Подскажите в чём моя ошибка. Может что-то упустил.

ISR (TIMER1_OVF_vect) // Прерывание по переполнению таймера 1
{
Отображение цифр на сегментах
}

ISR (TIMER1_COMPA_vect) //Прерывание по сравнению таймера 1
{
Гасим все разряды
}

// Главная программа
int main (void)
{
// Настраиваю таймер 1 для ШИМ
TCCR1A |= (0 << COM1A0)|(0 << COM1A1)|(1 << PWM1A); // Ножки микроконтроллера отключены от компаратора. Режим FASTPWM.
TCCR1B |= (1 << CS13)|(0 << CS12)|(1 << CS11)|(1 << CS10); //Предделитель на 1024, частота индикатора 2,6 кГц.
TCCR1D |= (0 << WGM10)|(0 << WGM11); //Режим FASTPWM
TIMSK |= (1 << TOIE1)|(1 << OCIE1A); // Разрешение прерываний таймера 1 по переполнению и сравнению
OCR1A = 50; // Начальное значение OCR1A. Яркость индикатора.

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

...остальная часть программы. Считывание температуры и вывод на индикатор.
}

Полный код программы под спойлером.
Спойлер#define F_CPU 8000000UL // Тактовая частота микроконтроллера 8 МГц
#define LEDS_OK // Раскомментировать, если используется индикатор с общим катодом

// Подключаю стандартные библиотеки
#include <avr/io.h> // Ножки ввода-вывода
#include <util/delay.h> // Задержки
#include <avr/interrupt.h> // Прерывания

// Сегменты, должны быть в пределах одного порта МК
#define LED_SEG_A 2
#define LED_SEG_B 0
#define LED_SEG_C 4
#define LED_SEG_D 6
#define LED_SEG_E 5
#define LED_SEG_F 1
#define LED_SEG_G 3
#define LED_SEG_DP 7
#define LED_SEG_PORT PORTB
#define LED_SEG_DDR DDRB

// Знакоместа, должны быть в пределах одного порта МК
#define LED_DIG_1A 2
#define LED_DIG_1B 3
#define LED_DIG_2A 1
#define LED_DIG_2B 4
#define LED_DIG_3A 0
#define LED_DIG_3B 5
#define LED_DIG_PORT PORTA
#define LED_DIG_DDR DDRA

// Датчик DS18B20 - любая свободная ножка МК
#define DS18B20 7
#define DS18B20_PORT PORTA
#define DS18B20_PIN PINA
#define DS18B20_DDR DDRA


// Массив для перекодировки цифры в набор сегментов для семисегментного индикатора
const uint8_t codes[16]=
{
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_E)|(1<<LED_SEG_F), // цифра 0
(1<<LED_SEG_B)|(1<<LED_SEG_C), // цифра 1
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_D)|(1<<LED_SEG_E)|(1<<LED_SEG_G), // цифра 2
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_G), // цифра 3
(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_F)|(1<<LED_SEG_G), // цифра 4
(1<<LED_SEG_A)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_F)|(1<<LED_SEG_G), // цифра 5
(1<<LED_SEG_A)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_E)|(1<<LED_SEG_F)|(1<<LED_SEG_G), // цифра 6
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_F), // цифра 7
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_E)|(1<<LED_SEG_F)|(1<<LED_SEG_G), // цифра 8
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_F)|(1<<LED_SEG_G), // цифра 9
0b00000000, // пробел (код 10)
(1<<LED_SEG_G), // прочерк (код 11)
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_F)|(1<<LED_SEG_G), // символ градуса (код 12)
(1<<LED_SEG_A)|(1<<LED_SEG_B)|(1<<LED_SEG_C)|(1<<LED_SEG_D)|(1<<LED_SEG_E)|(1<<LED_SEG_F)|(1<<LED_SEG_G)|(1<<LED_SEG_DP), // зажечь все сегменты (код 13)
(1<<LED_SEG_D)|(1<<LED_SEG_E)|(1<<LED_SEG_G), // буква "c" для вывода слова "crc" (код 14)
(1<<LED_SEG_E)|(1<<LED_SEG_G) // буква "r" для вывода слова "crc" (код 15)
};

#define SEG_BLANK 10 // пробел
#define SEG_MINUS 11 // прочерк
#define SEG_DEGREE 12 // символ градуса
#define SEG_ALL 13 // зажечь все сегменты
#define SEG_C 14 // буква "c" для вывода слова "crc"
#define SEG_R 15 // буква "r" для вывода слова "crc"

volatile uint8_t digit = 0; // Номер текущего знакоместа динамической индикации
volatile uint8_t digit1 = 0; // Цифра или символ, выводимые в 1 знакоместо
volatile uint8_t digit2 = 0; // Цифра или символ, выводимые во 2 знакоместо
volatile uint8_t digit3 = 0; // Цифра или символ, выводимые в 3 знакоместо

uint8_t DS_scratchpad[9] = {0,0,0,0,0,0,0,0,0}; // 9 байт, считанных с DS18B20, или так называемый "блокнот"
uint8_t Presense_errors = 0; // Счётчик ошибок - инициализация DS18B20
uint8_t Short_circuit_errors = 0; // Счётчик ошибок - КЗ линии данных DS18B20
int8_t Temperature = 0; // Температура преобразованная (целая часть градусов)


// Прерывание по переполнению таймера 1 (динамическая индикация)
ISR (TIMER1_OVF_vect)
{
///////////////////////////////////
// Индикатор с общим анодом (ОА)
///////////////////////////////////
// Выключаю все сегменты
#ifndef LEDS_OK
LED_SEG_PORT = ~(0b00000000);

// Деактивирую все знакоместа
LED_DIG_PORT &= ~((1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B));

// Отображаю цифру в одном из знакомест
switch (digit)
{
case 0:
{
LED_DIG_PORT |= (1<<LED_DIG_1A)|(1<<LED_DIG_1B); // Активирую 1 знакоместо
LED_SEG_PORT = ~(codes[digit1]); // На сегментах отображаю цифру
} break;
case 1:
{
LED_DIG_PORT |= (1<<LED_DIG_2A)|(1<<LED_DIG_2B); // Активирую 2 знакоместо
LED_SEG_PORT = ~(codes[digit2]); // На сегментах отображаю цифру
} break;
case 2:
{
LED_DIG_PORT |= (1<<LED_DIG_3A)|(1<<LED_DIG_3B); // Активирую 3 знакоместо
LED_SEG_PORT = ~(codes[digit3]); // На сегментах отображаю цифру
} break;
};

///////////////////////////////////
// Индикатор с общим катодом (ОК)
///////////////////////////////////
// Выключаю все сегменты
#else
LED_SEG_PORT = 0b00000000;

// Деактивирую все знакоместа
LED_DIG_PORT |= (1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B);

// Отображаю цифру в одном из знакомест
switch (digit)
{
case 0:
{
LED_DIG_PORT &= ~((1<<LED_DIG_1A)|(1<<LED_DIG_1B)); // Активирую 1 знакоместо
LED_SEG_PORT = codes[digit1]; // На сегментах отображаю цифру
} break;
case 1:
{
LED_DIG_PORT &= ~((1<<LED_DIG_2A)|(1<<LED_DIG_2B)); // Активирую 2 знакоместо
LED_SEG_PORT = codes[digit2]; // На сегментах отображаю цифру
} break;
case 2:
{
LED_DIG_PORT &= ~((1<<LED_DIG_3A)|(1<<LED_DIG_3B)); // Активирую 3 знакоместо
LED_SEG_PORT = codes[digit3]; // На сегментах отображаю цифру
} break;
};
#endif

// Готовлюсь к отображению следующего знакоместа
if (digit >= 2) digit = 0; else digit++;
}


// Инициализирую DS18B20
void DS18B20_init (void)
{
if ((DS18B20_PIN & (1 << DS18B20)) == 0) Short_circuit_errors++; // Проверяю КЗ линии данных
DS18B20_PORT &= ~(1 << DS18B20); // Устанавливаю низкий уровень
DS18B20_DDR |= (1 << DS18B20);
_delay_us(490);
DS18B20_DDR &= ~(1 << DS18B20);
_delay_us(68);
if ((DS18B20_PIN & (1 << DS18B20)) > 0) Presense_errors++; // Ловлю импульс присутствия датчика
// Если датчик не подключен, Presense_errors увеличиваю на 1
_delay_us(422);
}


// Функция чтения байта из DS18B20
uint8_t DS18B20_read (void)
{
uint8_t dat = 0;
for (uint8_t i=0; i<8; i++)
{
DS18B20_DDR |= (1 << DS18B20);
_delay_us(2);
DS18B20_DDR &= ~(1 << DS18B20);
_delay_us(4);
dat = dat >> 1;
if (DS18B20_PIN & (1 << DS18B20))
{
dat |= 0x80;
}
_delay_us(62);
}
return dat;
}


// Функция чтения "блокнота" из DS18B20
void DS18B20_read_scratchpad (void)
{
for (uint8_t i=0; i<9; i++) // Считываю 9 байт данных, или так называемый "блокнот"
{
DS_scratchpad[i] = DS18B20_read();
}
}


// Функция записи байта в DS18B20
void DS18B20_write (uint8_t dat)
{
for (uint8_t i=0; i<8; i++)
{
DS18B20_DDR |= (1 << DS18B20);
_delay_us(2);
if (dat & 0x01)
{
DS18B20_DDR &= ~(1 << DS18B20);
}
else
{
DS18B20_DDR |= (1 << DS18B20);
}
dat = dat >> 1;
_delay_us(62);
DS18B20_DDR &= ~(1 << DS18B20);
_delay_us(2);
}
}


// Алгоритм для вычисления CRC-8 для DALLAS.
// Для первого байта CRC = 0, для остальных - то, что получилось от предыдущего.
// В расчёт CRC входят первые 8 байт DS18B20.
// 1. Нахождение логического исключающего ИЛИ между младшим битом CRC и младшим битом данных.
// 2. Если результат равен 0, то:
// - Сдвиг вправо CRC.
// 3. Если результат равен 1, то:
// - Поиск нового значения CRC путем вычисления логического исключающего ИЛИ между CRC и полиномом CRC.
// - Сдвиг вправо CRC.
// - Установка старшего бита CRC в 1.
// - Сдвиг вправо данных.
// - Повтор данной последовательности 8 раз на 1 байт данных.
uint8_t DS18B20_crc (uint16_t adress)
{
uint8_t crc = 0; // Переменная для накопления CRC
for (uint8_t i=0; i<8; i++) // Считаю CRC 8-ми байт, 9-й байт это CRC
{
// Расчитываю CRC одного байта
crc = crc ^ (*(uint16_t*)(adress+i));
for (uint8_t j=0; j<8; j++)
{
if (crc & 0x01) crc = (crc >> 1) ^ 0x8C;
else crc >>= 1;
}
}
return crc; // Возвращаю CRC
}

//Прерывание по сравнению таймера 1 гасим все разряды
ISR (TIMER1_COMPA_vect)
{
///////////////////////////////////
// Индикатор с общим анодом (ОА)
///////////////////////////////////
#ifndef LEDS_OK
LED_DIG_PORT &= ~((1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B));
///////////////////////////////////
// Индикатор с общим катодом (ОК)
///////////////////////////////////
#else
LED_DIG_PORT |= (1<<LED_DIG_1A)|(1<<LED_DIG_1B)|(1<<LED_DIG_2A)|(1<<LED_DIG_2B)|(1<<LED_DIG_3A)|(1<<LED_DIG_3B);
#endif
}

// Главная программа
int main (void)
{
// Настраиваю ножки МК для сегментов
LED_SEG_DDR |= 0xFF;
LED_SEG_PORT |= 0x00;

// Настраиваю ножки МК для знакомест
LED_DIG_DDR |= (1 << LED_DIG_1A)|(1 << LED_DIG_1B)|(1 << LED_DIG_2A)|(1 << LED_DIG_2B)|(1 << LED_DIG_3A)|(1 << LED_DIG_3B);
LED_DIG_PORT |= 0x00;

// Настраиваю таймер 1 для ШИМ
TCCR1A |= (0 << COM1A0)|(0 << COM1A1)|(1 << PWM1A); // Ножки микроконтроллера отключены от компаратора. Режим FASTPWM.
TCCR1B |= (1 << CS13)|(0 << CS12)|(1 << CS11)|(1 << CS10); //предделитель на 1024, частота индикатора 2,6 кГц.
TCCR1D |= (0 << WGM10)|(0 << WGM11); //Режим FASTPWM
TIMSK |= (1 << TOIE1)|(1 << OCIE1A); // Разрешение прерываний таймера 1 по переполнению и сравнению
OCR1A = 50; // Начальное значение OCR1A. Яркость индикатора.

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

// При старте термометра делаю тест всех сегментов 0.5 секунды
digit1 = SEG_ALL;
digit2 = SEG_ALL;
digit3 = SEG_ALL;


while(1)
{
DS18B20_init(); // Инициализирую DS18B20
DS18B20_write(0xCC); // Пропускаю проверку серийного номера DS18B20
DS18B20_write(0x44); // Запускаю температурное преобразование
_delay_ms(1000); // Жду окончания температурного преобразования
DS18B20_init(); // Инициализирую DS18B20
DS18B20_write(0xCC); // Пропускаю проверку серийного номера DS18B20
DS18B20_write(0xBE); // Команда на чтение содержимого ОЗУ
DS18B20_read_scratchpad(); // Считываю "блокнот"
if (Presense_errors | Short_circuit_errors) // Если датчик не отвечает на Presense-импульс, либо КЗ линии данных
{
// Cтавлю "---" во всех разрядах семисегментного индикатора
digit1 = SEG_MINUS;
digit2 = SEG_MINUS;
digit3 = SEG_MINUS;
}
else
{
if (DS_scratchpad[8] == DS18B20_crc(&DS_scratchpad[0])) // Если принятая CRC совпала с расчётной CRC
{
Temperature = (int8_t)((DS_scratchpad[1] << 4)|(DS_scratchpad[0] >> 4)); // Совмещаю младший и старший байты, отбрасываю дробную часть, получаю температуру в градусах.

if (Temperature < 0)
// Отрицательная температура
{
Temperature =-Temperature; // Перевожу отрицательное число в положительное
digit1 = SEG_MINUS; // Символ "-"
if (Temperature < 10)
{
// -9*...-1*
digit2 = Temperature % 10; // Единицы градусов
digit3 = SEG_DEGREE; // Символ градуса
}
else
{
// -55...-10
digit2 = Temperature % 100 / 10; // Десятки градусов
digit3 = Temperature % 10; // Единицы градусов
}
}
else
// Положительная температура
{
if (Temperature > 99)
{
// 100...125
digit1 = Temperature % 1000 / 100; // Сотни градусов
digit2 = Temperature % 100 / 10; // Десятки градусов
digit3 = Temperature % 10; // Единицы градусов
}
else
{
if (Temperature > 9)
{
// 10*...99*
digit1 = Temperature % 100 / 10; // Десятки градусов
digit2 = Temperature % 10; // Единицы градусов
digit3 = SEG_DEGREE; // Символ градуса
}
else
{
// 0*...9*
digit1 = SEG_BLANK; // Пустой символ
digit2 = Temperature % 10; // Единицы градусов
digit3 = SEG_DEGREE; // Символ градуса
}
}
}
}
else // Если принятая CRC не совпала с расчётной, выводим надпись "crc" на семисегментный индикатор
{
digit1 = SEG_C; // "c"
digit2 = SEG_R; // "r"
digit3 = SEG_C; // "c"
}
}
Presense_errors=Short_circuit_errors=0; // Сбрасываю счётчик ошибок инициализации DS18B20, сбрасываю флаг КЗ
}
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вс дек 04, 2016 11:54:04 
Прорезались зубы
Аватар пользователя

Карма: 4
Рейтинг сообщений: 27
Зарегистрирован: Чт янв 08, 2015 22:31:15
Сообщений: 247
Рейтинг сообщения: 0
Разобрался. Я моделировал в Proteus, а в нём почему то ШИМ не работает, возможно это связано с тем, что семисегментные индикаторы в нём не умеют менять яркость. Хотя на осциллографе должна изменяться скважность импульсов подаваемых на катоды/аноды, но почему то и этого не происходит. В общем Proteus для моделирования таких задач не подходит.
На реальном железе всё работает, как нельзя лучше. Яркость изменяется в зависимости от значения регистра OCR1A. Чем оно выше, тем выше яркость.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт дек 15, 2016 14:11:21 
Опытный кот
Аватар пользователя

Карма: 7
Рейтинг сообщений: 48
Зарегистрирован: Вт июн 17, 2014 00:34:26
Сообщений: 791
Рейтинг сообщения: 0
Добрый день, на вход функции надо подать число в формате Q15, это число с фиксированной точкой где 1бит отводится под целую часть и 15 под дробную часть. У меня же данные, которые хотелось бы подать хранятся в uint16_t.
Нужно ли как то преобразовывать uint16_t или можно подать так?
Мне думается, что можно подать без каких-либо преобразований uint16_t?
Подскажите пожалуйста как правильно?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт дек 15, 2016 14:17:38 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 98
Рейтинг сообщений: 2116
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18403
Откуда: Новочеркасск
Рейтинг сообщения: 1
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
baghear писал(а):
Подскажите пожалуйста как правильно?
если сами биты в вашем числе расположены в соответствии с требованиями функции, то можно подать. для исключения предупреждения компилятора при подаче рекомендую принудительно привести число к требуемому типу.

как-то так: my_func((Q15)my_int16_var);

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт дек 15, 2016 14:26:19 
Опытный кот
Аватар пользователя

Карма: 7
Рейтинг сообщений: 48
Зарегистрирован: Вт июн 17, 2014 00:34:26
Сообщений: 791
Рейтинг сообщения: 0
Спасибо!!!
Ещё вопрос входной и выходной формат функции отличается, как показано в таблице.
Что указывается в последнем столбце.

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


Вложения:
Screenshot_1.jpg [37.72 KiB]
Скачиваний: 550
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт дек 15, 2016 15:46:42 
Вымогатель припоя
Аватар пользователя

Карма: 19
Рейтинг сообщений: 230
Зарегистрирован: Чт окт 06, 2016 21:12:07
Сообщений: 606
Откуда: Южное Бутово
Рейтинг сообщения: 1
Не уверен, что это так, но очень похоже на формат двоичного числа с фиксированной точкой, где в таблице указываетя количество бит до десятичной точки и количество бит после нее.
То есть, в последней колонке указано, на сколько бит вправо смещена десятичная точка, относительно формата во второй колонке.

_________________
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт дек 15, 2016 18:29:44 
Опытный кот
Аватар пользователя

Карма: 7
Рейтинг сообщений: 48
Зарегистрирован: Вт июн 17, 2014 00:34:26
Сообщений: 791
Рейтинг сообщения: 0
Спасибо, похоже Вы правы.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср дек 21, 2016 08:58:53 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Други-знатоки, помогите, если не трудно, разобраться в указателях :?

По определению указатель есть переменная, которая содержит в себе адрес другой переменной. Определение в общем понятно.
Непонятно следующее: если он (указатель) содержит адрес, который обычно не занимает меньше 16 бит, то почему его всегда ориентируют на размерность переменной, на которую он указывает?
Если, скажем, имеется массив char array[10], то почему указатель на него *ptr тоже должен быть типа char? Ведь адрес, по которому размещается массив, скорее всего не менее 16 бит?

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср дек 21, 2016 09:22:28 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1035
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4884
Откуда: Минск
Рейтинг сообщения: 0
Zhuk72 писал(а):
если он (указатель) содержит адрес, который обычно не занимает меньше 16 бит, то почему его всегда ориентируют на размерность переменной, на которую он указывает?
Ничего подобного, Вы немного запутались. Все указатели, на любые типы, имеют один и тот же размер.
Цитата:
Если, скажем, имеется массив char array[10], то почему указатель на него *ptr тоже должен быть типа char?

Не так. Правильно не "указатель *ptr типа char", а "указатель ptr типа char*".

В данном случае, например, если вы пишете что-то вроде
Код:
char array[10];
char *ptr = array;

То указатель - это ptr. Не *ptr (это, вообще-то, разыменование указателя - т.е., содержимое ячейки, куда он указывает), а именно ptr. И тип у него - char* (указывающий на char).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср дек 21, 2016 10:18:40 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Спасибо за разъяснение!
Т.е. запись char *ptr означает, что содержимое ячейки, на которую указывает ptr имеет тип char. Верно?
Соответственно
Код:
char array[10];
char *ptr = array;
равносильно
Код:
char array[10];
char *ptr;

ptr = array;

Я правильно понимаю?

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 7669 ]     ... , , , 243, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y