Перейти к содержанию

dm37

Members
  • Постов

    252
  • Зарегистрирован

  • Посещение

Весь контент dm37

  1. 4 штуки включаются в параллель как раз для повышения чувствительности, и анализируют как количество импульсов так и длину. Правильнее сказать анализируют площадь за единицу времени (постоянная времени), потом делят на 4. Причём постоянная времени должна меняться в зависимости от уровня излучения. Подавать на микроконтроллер сырой сигнал может не получиться, как правило ставиться обработка на операционниках (в интегральном включении), а на микроконтроллер (лучше DSP) подают либо частоту, либо уровень, пропорционально излучению, кому что нравиться.
  2. Что вы подразумеваете под словом "сыпятся", как они себя ведут, перестают отвечать? У нас датчики (DS1820, DS18S20, DS18B20) без гильз (покрытые лаком) и в гильзах работают более 10 лет в режиме 24/7. Может всё же датчики плохо "упакованы" в гильзы. Наши условия: диапазон температур +5 до +50
  3. по С++ обновил описание https://ru.files.fm/u/a2sfccuf#/list/ файл uC_cpp.7z
  4. Можете не прописывать, я предложил более быстрый вариант получения результата по формуле (предварительные расчёты можно провести в Excel). Можно пойти другим путём написать функцию расчёта дБ (исключив работу с дробями): signed int get_dB(unsigned char N) { return(315-(5*(255-N))); } на выходе для N=0 получите dB = -960 и дальше выводите значение на индикатор, с учётом, что запятую нужно сместить влево на один разряд, т.е. "-96,0" (для N=1 dB=-955 на индикаторе "-95,5") Обычно полученное значение помещается в буфер (массив), у вас на 4 знакоместа, лучше в буфер помещать преобразованный код #define SEG_A (1<<0) #define SEG_B (1<<1) #define SEG_C (1<<2) #define SEG_D (1<<3) #define SEG_E (1<<4) #define SEG_F (1<<5) #define SEG_G (1<<6) #define SEG_P (1<<7) // Таблица перекодироки для отображения цифр static const uint8_t __flash TableLED_7Seg_Digit[] = { ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F ), // 0 ( SEG_B | SEG_C ), // 1 ( SEG_A | SEG_B | SEG_G | SEG_E | SEG_D ), // 2 ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_G), // 3 ( SEG_B | SEG_C | SEG_F | SEG_G ), // 4 ( SEG_A | SEG_C | SEG_D | SEG_F | SEG_G ), // 5 ( SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G ), // 6 ( SEG_A | SEG_B | SEG_C ), // 7 ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G ), // 8 ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G ) // 9 }; static inline uint8_t GetLEDDigit(uint8_t value) { return(TableLED_7Seg_Digit[value]); } как у вас реализован вывод на 7-сегментники не знаю, схемы нет
  5. т.е. N в диапазоне от 0 до 255? Если так, то можно сделать массив на 256 элементов. Тип элемента определяете сами (например, signed char или signed int). Заранее рассчитываете значения дБ при всех значениях N и помещаете результат в массив. Результат получаете так: dB = mas[N]; а далее вывод на дисплей (это для LCD, но думаю не сложно будет переделать под LED). Я обычно для LED кладу в буфер уже преобразованный для 7-сегментного индикатора код. Чтобы в прерывании ничего не преобразовывать, а только выводить в порт. //============================================================================ // Вывести целое число беззнаковое 16 бит // pos - позиция экрана // value - отображаемое значение // width - количество отображаемых символов // ch - символ заполнения ведущих пробелов //============================================================================ void ShowValueUI16(uint8_t pos, uint16_t value, uint8_t width, uint8_t ch) { uint8_t *disp; uint16_t i; disp = Display + pos + width; // указатель на знакоместо младшего разряда *--disp = value % 10 + '0'; for(i = 10; width > 1; i *= 10, width--) { if((value / i) > 0) *--disp = (value / i) % 10 + '0'; else *--disp = ch; // ведущие символы ('0' или ' ') } } //============================================================================ // Вывести целое число знаковое 16 бит // pos - позиция экрана // value - отображаемое значение // width - количество отображаемых символов // ch - символ заполнения ведущих пробелов //============================================================================ void ShowValueSI16(uint8_t pos, int16_t value, uint8_t width, uint8_t ch) { uint8_t *disp; disp = Display + pos; // указатель на знакоместо младшего разряда if(value >= 0) // опеределяем знак *disp++ = ' '; else { *disp++ = '-'; value = -value; } ShowValueUI16(pos+1, value, width, ch); }
  6. Ну если применительно к тому, что я писал, то: - создать класс драйвера выходного устройства (например DrvLed8), в классе драйвера создать два метода: DrvLed8::Init() - инициализация пинов контроллера, DrvLed8::Set(uint8_t mask) - включение/выключение светодиодов в зависимости от маски (0xAA, 0x55) - создать класс устройства DevLed8 с одним методом DevLed8::Tick(), в котором будет осуществляться смена маски для DrvLed8::Set(uint8_t mask) - создать счётчик TCounter, для определения (изменения) скорости мигания (если доработать, то, например, через метод TCounter::Set(uint16_t value) можно менять скорость мигания, при наличии кнопок, конечно) - настроить прерывание на 1 млсек (можно другое значение). В прерывании выполнять Counter::Tick() а дальше примерно так typedef TFlags < 1 > Flags; // хранилище флагов на 1 флаг typedef TFlag < Flags, 0 > FCounter; // флаг для работы счётчика typedef TDevLed8 < TDrvLed8 > DevLed8; // устройство управления 8 светодиодами typedef TCounter < 200, FCounter > Counter; // счётчик на 200 млсек typedef TTimer0_SimpleCycle < TTimerValue < 1 > ::ms > Timer_1ms; // настройка таймера на 1 млсек //--------------------------------------------------------- struct IRQ_1ms { #pragma inline = forced static inline void execute(void) { Counter::Tick(); } }; template void IRQ_Timer0_CompareA < IRQ_1ms > ::execute(); //--------------------------------------------------------- void main(void) { DevLed8::Init(); Timer_1ms::Init(); Counter::Init(); Timer_1ms::Start(); _SEI(); while(1) { if(Counter::Check()) { DevLed8::Tick(); Counter::Reset(); } } } После можно будет добавить в класс DevLed8 метод SetMode(uint8_t mode) для задания номера эффекта
  7. То, что у меня получилось на C++, можно посмотреть здесь https://ru.files.fm/u/a2sfccuf#/list/, файл uC_cpp.7z Внутри: - пример с динамической индикацией (исходники + proteus) - пример с LCD на HD44780 (исходники + proteus) - небольшое описание Микроконтроллеры ATtiny2313 и ATmega32, компилятор IAR
  8. никто и не спорит, мы не знаем тип uC у ТС. Я не собирался что-то доказывать, просто привел код который использую. Ваш код напрашивается привести к следующему виду (возьму себе для дальнейшего использования): u08 hex_bcd_time (u08 a) { u08 temp = a; u08 cnt = 0; while(temp >= 10) { temp -= 10; cnt++; } return ((cnt << 4) | temp); // temp уже проверили и он меньше 10 (маска не нужна) }
  9. //============================================================================== // Преобразование из BCD в BIN //============================================================================== uint8_t BCDToBin(uint8_t byte) { return((byte & 0x0F) + (byte >> 4) * 10); } //============================================================================== // Преобразование из BIN в BCD //============================================================================== uint8_t BinToBCD(uint8_t byte) { return(((byte / 10) << 4) + (byte % 10)); }
  10. Время, хранятся в формате BCD. Т.е., например, единицы минут хранятся в младших 4 битах, а десятки минут хранятся в старших 3 битах. Необходим перевод числа и BCD в BIN при чтении, ну и при записи из BIN в BCD.
  11. 0xD0 - адрес микросхемы для записи 0xD1 - адрес микросхемы для чтения и больше ничего нет
  12. что значит адрес часов? а что тогда такое 0xD0?
  13. а что это за число? у меня это выглядит так
  14. Скорее всего это и есть причина порчи прошивки, т.к. по питанию у вас наверно стоит конденсатор на 1000 мкФ. При отключении блока напряжения питания плавно опускается и контроллер продолжает работать пока не отключиться и что он будет делать при сильно пониженном напряжении неизвестно, Как правило это портит прошивку. Монитор питания по Reset отключает микроконтроллер до снижения питания ниже допустимого уровня. Если в микроконтроллере есть встроенный монитор питания, можно попробовать включить его. Я предпочитаю внешний монитор питания.
  15. а что стоит по RESET? У нас слетала прошивка - пришлось ставить внешний монитор питания MCP100-450DI. Проблемы исчезли.
  16. Сделайте на таймере прерывание на 1 млсек и посмотрите сколько получилось с переменными разного типа
  17. dm37

    STM32 для чайника

    делали небольшую сеть на https://www.compel.ru/infosheet/TELC/RXQ1-433 Один мастер и несколько ведомых. Правда пришлось в последствии отказаться от этой идеи, кто то по близости в 23:00 включал что-то, а в 08:00 выключал. Нас это не устраивало. Сейчас там оптика проложена.
  18. dm37

    STM32 для чайника

    будет идти случайный набор "0" и "1" (шум), а uart будет это воспринимать как байты
  19. dm37

    STM32 для чайника

    Похоже, что это достаточно простые модули, поэтому нельзя просто передавать данные из uart, необходимо их перекодировать в код, который на выходе будет обеспечивать минимум постоянной составляющей (равное количество "0" и "1" за короткий промежуток времени, избегать передачи подряд большого количества "0" или "1"). Например можно взять код манчестера (предпочтительнее) или 4b/5b. Остальные сложнее в реализации. Сначала передаётся преамбула, для синхронизации (например, 48 бит 01010101...), потом пакет с байтстафингом (т.е. уникальный признак пакета), и конечно CRC. И надо учитывать что с модуля радиоканала всегда будет идти какой то мусор, Ваша задача поймать в этом мусоре синхронизацию и байт "признак начала пакета". Посмотрите файл из вложения. nAN400-07rev1_2.pdf Здесь указано, что "Modulation rate:2Kbit/s", т.е. скорость будет не высокой. http://p.globalsources.com/IMAGES/PDT/SPEC/016/K1042395016.pdf AN43.pdf
  20. уверяю, результат вас разочарует. Потратьте время на вылизывание кода работы с датчиком, без этого ваш проект может не заработать как вы задумывали
  21. он не простой, он неправильный, даже не проверяется контрольная сумма (CRC) при приёме
  22. вот так и рождается плохой код
  23. Вообще код немного странный (плохой пример для изучения). 1) почему вы решили что "импульс присутствия" датчика должен попадать только на момент выполнения кода функции DS18B20_init(), а если попадёт на строку _delay_ms(1000), что тогда? Вы импульс пропустите 2) зачем после выполнения функции DS18B20_init() вы выполняете другие функции по работе с датчиком если датчик не ответил. Уберите проверку на обнаружение датчика по "импульсу присутствия". Работайте с датчиком как будто он всегда есть, т.е. наличие датчика определяется по CRC. Если вы всё же хотите использовать "импульс присутствия", то надо использовать прерывания (INT0 например). 3) лучше данный код писать на ассемблере, на Си можно если вы отключите оптимизацию и будете знать, сколько времени выполняется тот или иной участок кода 4) лучший вариант, взять datasheet на DS18B20 и начать по диаграммам писать свой код, конечно анализируя сторонние примеры. 5) код подобный этому "DDRC |= (1 << PC0);"уже говорит о том, что пример не очень хороший. Надо как минимум использовать макросы.
  24. для использования команды rcall необходимо в начале программы инициализировать стек: LDI R16, low(RAMEND) OUT SPL, R16 LDI R16, high(RAMEND) OUT SPH, R16
×
×
  • Создать...