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

Re: TMP03F эмулятор на 1wire

Вс сен 22, 2019 15:15:45

ну, тогда и тинька13 справится - на тупых задержках :) пока формируется Т1, идет общение с DS18x20, а потом при помощи _delay_us формируется Т2 :)
если на ассемблере писать, то и attiny9 хватит, пожалуй :)))

Да и на сях хватит attiny10/9. ШИМ генерить - копейки кода. Считать с 1-Wire температуру знамо как, код влезает в тиньки эти. У меня в тини10 прекрасно влез код софтового I2C, опроса датчика освещенности и расстояния. На C.

Re: TMP03F эмулятор на 1wire

Пн сен 23, 2019 06:41:11

В качестве ликбеза, приведите код и hex для tiny10/9. На входе данные, считанные из DS18B20 один раз в 10 секунд, на выходе ШИМ Т1+Т2 в формате TMP03/04. :oops:

Re: TMP03F эмулятор на 1wire

Пн сен 23, 2019 13:10:19

Это уже не "ликбез", а реализация )

Вот на очень скорую руку состряпал. Не проверял в работе и не планирую ,т.к. мне это не нужно. Код для DS18B20 взял с сети первый попавшийся.
EDIT: Поправил код, отошел и вспомнил что забыл в одном месте канал ШИМа A на B сменить.

Исходник.
Спойлер
Код:
/*
 * File:   ds18b20-tmp03f-conv.c
 * Author: nstorm
 * DS18B20 code author: http://blablacode.ru/mikrokontrollery/442
 */

#define F_CPU 8000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <math.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include "ds18b20-tmp03f-conv.h"

// Global temp
temp_t temp;
volatile uint16_t pwm_reg;

// сброс датчика
uint8_t therm_reset() {
    uint8_t i;
    // опускаем ногу вниз на 480uS
    THERM_LOW();
    THERM_OUTPUT_MODE();
    _delay_us(480); // замените функцию задержки на свою
    // подымаем линию на 60uS
    THERM_INPUT_MODE();
    _delay_us(60);
    // получаем значение на линии в период 480uS
    i = (THERM_PIN & (1 << THERM_DQ));
    _delay_us(420);
    // возвращаем значение (0=OK, 1=датчик не найден)
    return i;
}


// функция отправки бита
void therm_write_bit(uint8_t bit) {
    // опускаем на 1uS
    THERM_LOW();
    THERM_OUTPUT_MODE();
    _delay_us(1);
    // если хотим отправить 1, поднимаем линию (если нет, оставляем как есть)
    if (bit) THERM_INPUT_MODE();
    // ждем 60uS и поднимаем линию
    _delay_us(60);
    THERM_INPUT_MODE();
}

// чтение бита
uint8_t therm_read_bit(void) {
    uint8_t bit = 0;
    // опускаем на 1uS
    THERM_LOW();
    THERM_OUTPUT_MODE();
    _delay_us(1);
    // поднимаем на 14uS
    THERM_INPUT_MODE();
    _delay_us(14);
    // читаем состояние
    if (THERM_PIN & (1 << THERM_DQ)) bit = 1;
    // ждем 45 мкс и возвращаем значение
    _delay_us(45);
    return bit;
}

// читаем байт
uint8_t therm_read_byte(void) {
    uint8_t i = 8, n = 0;
    while (i--) {
        // сдвигаем в право на 1 и сохраняем следующее значение
        n >>= 1;
        n |= (therm_read_bit() << 7);
    }
    return n;
}

// отправляем байт
void therm_write_byte(uint8_t byte) {
    uint8_t i = 8;
    while (i--) {
        // отправляем бит и сдвигаем вправо на 1
        therm_write_bit(byte & 1);
        byte >>= 1;
    }
}

void therm_convert() {
    therm_reset();
    therm_write_byte(THERM_CMD_SKIPROM);
    therm_write_byte(THERM_CMD_CONVERTTEMP);
}

// читаем температуру с датчика
bool therm_read_temperature() {
    uint8_t temperature[2];

    if (!therm_read_bit())
        return false;

    therm_reset();
    therm_write_byte(THERM_CMD_SKIPROM);
    therm_write_byte(THERM_CMD_RSCRATCHPAD);

    temperature[0] = therm_read_byte();
    temperature[1] = therm_read_byte();
    therm_reset();

    temp.digit = temperature[0] >> 4;
    temp.digit |= (temperature[1] & 0x7) << 4;

    temp.decimal = temperature[0] & 0xF;
    temp.decimal *= THERM_DECIMAL_STEPS_12BIT;
   
    return true;
}

void update_pwm_reg() {
    cli();
    pwm_reg = ((uint32_t)(TMP_LOW_CNT * 400) / (235 - temp.digit));
    sei();
}

void read_and_update() {
    therm_convert();
    while (!therm_read_temperature());
    update_pwm_reg();   
}

ISR(TIM0_COMPB_vect) {
    OCR0A = pwm_reg;
}

void init() {
   cli(); // Disable interrupts
   CCP = 0xD8; // Magic number to enable configuration access
   CLKMSR = 0b00; // Internal osc
   _NOP();
    _NOP();
    _NOP();
   CCP = 0xD8;
   CLKPSR = 0; // Prescaler 1:1 = 8 MHz system clock
   ACSR |= (1 << 7); // ACD (ACD: Analog Comparator Disable = 1)
   PRR = 0b11; // Power Reduction Register
   sei(); // Enable interrupts

   THERM_DDR = 0xFF; //

    /* Timer init
     * PWM, Phase & Freq. Correct, TOP = OCR0A, 1:8 prescaler
     * Counting up: Set OC0A/OC0B on compare match
     * Counting down: Clear OC0A/OC0B on compare match
     */
    TCCR0A = (1 << WGM00) | (1 << COM0B0) | (1 << COM0B1);
    TCCR0B = (1 << WGM03) | (1 << CS01);
    TCCR0C = 0;
    TIMSK0 = (1 << OCIE0B); // Enable OC0B interrupt (at BOTTOM)
}

int main(void) {
    init();   

    // Initial temp reading
    read_and_update();
    OCR0A = pwm_reg;
    OCR0B = TMP_LOW_CNT;
   
    PRR = (1 << PRTIM0); // Enable Timer0

    while (1) {
        read_and_update();
    }
}


Хидер
Спойлер
Код:
/*                                                                                                                                                                                                                                           
 * File:   ds18b20-tmp03f-conv.h                                                                                                                                                                                                             
 * Author: nstorm                                                                                                                                                                                                                           
 */                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                             
#include <stdint.h>                                                                                                                                                                                                                         
                                                                                                                                                                                                                                             
#ifndef DS18B20_TMP03F_CONV_H                                                                                                                                                                                                               
#define DS18B20_TMP03F_CONV_H                                                                                                                                                                                                               
                                                                                                                                                                                                                                             
/* Определяем куда подключен датчик */
#define THERM_PORT PORTB
#define THERM_DDR DDRB
#define THERM_PIN PINB
#define THERM_DQ PB2
/* Макросы для "дергания ноги" и изменения режима ввода/вывода */
#define THERM_INPUT_MODE() THERM_DDR &= ~(1 << THERM_DQ)
#define THERM_OUTPUT_MODE() THERM_DDR |= (1 << THERM_DQ)
#define THERM_LOW() THERM_PORT &= ~(1 << THERM_DQ)
#define THERM_HIGH() THERM_PORT |= (1 << THERM_DQ)

// команды управления датчиком
#define THERM_CMD_CONVERTTEMP 0x44
#define THERM_CMD_RSCRATCHPAD 0xBE
#define THERM_CMD_WSCRATCHPAD 0x4E
#define THERM_CMD_CPYSCRATCHPAD 0x48
#define THERM_CMD_RECEEPROM 0xB8
#define THERM_CMD_RPWRSUPPLY 0xB4
#define THERM_CMD_SEARCHROM 0xF0
#define THERM_CMD_READROM 0x33
#define THERM_CMD_MATCHROM 0x55
#define THERM_CMD_SKIPROM 0xCC
#define THERM_CMD_ALARMSEARCH 0xEC

#define THERM_DECIMAL_STEPS_12BIT 625 //.0625

#define TMP_LOW_US 12000
#define TMP_LOW_CNT (uint16_t)(TMP_LOW_US/2)

typedef struct {
    int8_t digit;
    uint16_t decimal;   
} temp_t;

#endif  /* DS18B20_TMP03F_CONV_H */


Хекс
Спойлер
Код:
:100000000AC019C018C017C016C015C09FC013C0C1
:1000100012C011C010C011271FBFCFE5D0E0DEBF56
:10002000CDBF20E0A0E4B0E001C01D93A534B2072D
:10003000E1F79ED0F9C0E4CF49E0415071F0129849
:100040000A9A52E05A95F1F700C080FD0A9850EAEA
:100050005A95F1F70A988695F0CF089512980A9A62
:1000600042E04A95F1F700C00A9845E24A95F1F757
:10007000000080B148E74A95F1F782FB882780F9B4
:100080000895CF93DF93D9E0C0E0D15039F0E6DF97
:10009000879588278795C695C82BF7CF8C2FDF913A
:1000A000CF91089512980A9A4FEB53E04150504077
:1000B000E9F700C000000A9850EA5A95F1F780B1BC
:1000C00047E453E041505040E9F700C0000084701D
:1000D00008952F933F93CF93E5DF8CECADDF84E45D
:1000E000ABDFBCDF8823E9F3DDDF8CECA5DF8EEB33
:1000F000A3DFC7DFC82FC5DF382FD4DF37703295B5
:10010000307F4C2F42954F70342B30A98C2F8F703D
:1001100090E061E772E04FD092A981A9F89440A1E4
:100120002BEE30E0241B310B47FD3395032F000FDE
:10013000440B550B60E07FE980E090E04ED034A99D
:1001400023A97894CF913F912F9108951F930F93F6
:100150000FB70F9310E04F935F9343A154A157BD86
:1001600046BD5F914F910F910FBF0F911F91189551
:10017000F89448ED4CBF17BF0000000000004CBFD2
:1001800016BFFF9A43E045BF78944FEF41B941E372
:100190004EBD42E14DBD1CBD44E04BBD9ADF43A1C5
:1001A00054A157BD46BD40E757E155BD44BD41E0B0
:1001B00045BF8FDFFECF0027552704C0080F591F0A
:1001C000880F991F8050904029F076956795B0F37D
:1001D0007107B1F7802F952F0895A1E21A2FAA1B5E
:1001E000BB1BEA2FFB2F0DC0AA1FBB1FEE1FFF1F5B
:1001F000A217B307E407F50720F0A21BB30BE40B2B
:10020000F50B661F771F881F991F1A9569F7609570
:10021000709580959095262F372F482F592F6A2F4C
:0C0220007B2F8E2F9F2F0895F894FFCFA6
:00000001FF

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 08:58:35

Что, никто не проверял? Никому не надо?

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 11:09:15

Нарисуй схему и фьюзы какие, я проверю на железе на след неделе. Тини13 тини2313 вроде еще какоц то 8 ногий есть завтра напишу

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 11:39:44

Это для тини10. Фьюзы трогать не надо, PB2 - данные от DS18B20, OC0B - вывод ШИМ.

Изображение

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 13:55:30

Что, никто не проверял? Никому не надо?
Мне например нужно. :) Только вот нет у меня ATtiny10, есть ATtiny13. :(

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 14:25:22

korob, у 13ой тиньки таймер 8-битный - неудобно. И само собой точность хуже будет. Написать можно, но куда сложнее. А под тиньку10 за счет 16-битного таймера всё аппаратно работает и просто. Тиньки 10ые даже в ЧиД по 50р есть, на Али еще дешевле.
А для 2313 на прошлой странице уже на АСМе написали вариант. Я мельком глянул сейчас - почти аналог того, что для C написал для т10. Только у меня Phase & Freq correct PWM режим используется, а там Fast PWM. Там кстати тоже 16-битный таймер есть, вот и вся прелесть.

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 15:02:07

NStorm В качестве ликбеза. Правильно ли понимаю, что
Код:
 temp.digit = temperature[0] >> 4;
    temp.digit |= (temperature[1] & 0x7) << 4;
блокирует отрицательную область температур 18B20?

Оператор
Код:
PRR = (1 << PRTIM0); // Enable Timer0
наоборот, запретит тактированиеТ0.

Re: TMP03F эмулятор на 1wire

Пт сен 27, 2019 15:44:10

akl, правильно, нашли ошибки. Код для DS я как уже сказал нашел в сети и особо не глядел. Проглядел этот момент. Криво конечно, надо 2's нормально считать.
PRR надо 0 в PRTIM0 записать, PRR = ~(1 << PRTIM0);

Re: TMP03F эмулятор на 1wire

Пн сен 30, 2019 11:16:24

Пофиксил ошибочки. https://github.com/N-Storm/ds18b20-tmp03f-conv - сюда кинул актуальную версию.

Re: TMP03F эмулятор на 1wire

Ср окт 02, 2019 05:59:16

Дополнил измерением температуры. Проверил с имеющимся у меня датчиком DS18B20P с паразитным!!! питанием. Работа с датчиком по линии PB7 (подтяжка - внешний резистор 1,1к ), признак присутствия датчика - лог.1 на PB0. При отсутствии датчика формируется ШИМ соответствующий -100ºC. Выход ШИМ на PB4/OC1B.
15:10
Нашел ошибку. Заменил файлы. Ток потребления при 3,6V ~4мА. Во время преобразования возрастает до 5мА. Период преобразования порядка 6...9 секунд.
Вложения
TMP03_2313_V2.zip
(3.07 KiB) Скачиваний: 234
Ответить