Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Исходники » Очередные часы с термометром и гигрометром


Очередные часы с термометром и гигрометром

Сообщений 1 страница 5 из 5

1

Всем доброго времени суток!
Процесс изучения работы LCD дисплея 1602 с PCF8574T по шине I2C привел меня к следующему как сказать к следующему устройству и небольшому тупику... подробнее...
Имеем LCD дисплей 1602 с припаянной платкой на PCF8574T для работы по шине I2C, датчик температуры и влажности DHT11 и часы реального времени DS1302, мозгом всего этого является atmega 32L тактируемая от внешнего кварца на 16 мГц ну и питание 5в.
Данное устройство выводит на дисплей значения влажности и температуры, а так же по логике должно выводить время и дату, но с этим некие проблемы, выводятся нули и мерцают где то с интервалом раз в секунду.
Ниже, что то типа скриншота
00:00:00   Т: 25С
00/00/00   Н: 58%

Код ниже

Код:
 $Regfile="m32def.dat"
$Crystal=16000000
$hwstack=100
$swstack=100
$framesize=100
$baud = 19200

$lib "i2c_twi.lbx"                                ' die "echte" TWI benutzen
$lib "ds1302clock.lib"


'------------------------------------------------------------------------------
' Definition von HW-Ressourcen
'------------------------------------------------------------------------------

Sda_port Alias Portc.1                            'Definition der I2C-Ports
Scl_port Alias Portc.0

Config Sda = Sda_port
Config Scl = Scl_port

'объявление подпрограммы
Declare Sub Get_th(t As Byte , H As Byte)

Config Serialin = Buffered , Size = 128
Config Serialout = Buffered , Size = 128

'подключение датчика к PortD.6
Dht_put Alias Portd.6
Dht_get Alias Pind.6
Dht_io_set Alias Ddrd.6

Config Portc.4 = Output
Config Portc.6 = Output

Ds1302_clock Alias Portc.4                                  ' DS1302 Pin 7 - Clock
Ds1302_io Alias Pinc.5                                      ' DS1302 Pin 6 - I/O
Ds1302_io_port Alias Portc.5
Ds1302_enable Alias Portc.6                                 ' DS1302 Pin 5 - Enable

Declare Sub Ds1302_write(byval Clockcommand As Byte , Clockbyte As Byte)
Declare Function Ds1302_read(byval Clockcomand As Byte) As Byte
Declare Sub Ds1302_set_time(byval Strtime As String)

Dim T As Byte                        'перееменная для хранения температуры
Dim H As Byte                        'переменная для хранения влажности
Dim Crc As Byte                      'переменная для хранения байта четности
Dim Mybyte As Byte
Dim Sensor_data As String * 40    'сюда будут записываться данные отсылаемые датчиком
Dim Tmp_str8 As String * 8
Dim Count As Byte                    'переменная для подсчета принятых бит

dim t_str as string*3
dim 1_line_str as string*20

dim h_str as string*3
dim 1_line_strh as string*20

Config Clock = User

Config Date = Ymd , Separator = -

Enable Interrupts

Set Dht_io_set
Set Dht_put

'------------------------------------------------------------------------------
' Definition von SW-Ressourcen
'------------------------------------------------------------------------------

'Const Addr_lcd_pcf_r = &h41
Const Addr_lcd_pcf_w = &H4E ' &H4E                      'Adresse des PCF8574

Dim Lcd_beleuchtung As Bit
Set Lcd_beleuchtung                               'LCD_Beleuchtung einschalten
'Reset Lcd_beleuchtung                                       'LCD_Beleuchtung ausschalten

Dim I As Byte                                     'Z?hler-Variable

Dim Lcd_port As Byte                              'Definition des LCDs am PCF8574
Lcd_port_rs Alias Lcd_port.0                      'Display-Pin RS an Port.0
Lcd_port_rw Alias Lcd_port.1                      'Display-Pin R/W an Port.1
Lcd_port_e Alias Lcd_port.2                       'Display-Pin E an Port.2
Lcd_port_bel Alias Lcd_port.3                     'Beleuchtung an Port.3
Lcd_port_db4 Alias Lcd_port.4                     'Display-Pin DB4 an Port.4
Lcd_port_db5 Alias Lcd_port.5                     'Display-Pin DB5 an Port.5
Lcd_port_db6 Alias Lcd_port.6                     'Display-Pin DB6 an Port.6
Lcd_port_db7 Alias Lcd_port.7                     'Display-Pin DB7 an Port.7

'------------------------------------------------------------------------------
' Definition von Subs / Prototyping
'------------------------------------------------------------------------------

Declare Sub Lcd_write(byval Text As String )      'Die Funktion zum Schreiben von Text auf das Display

'------------------------------------------------------------------------------
' Programm - Initialisierungen
'------------------------------------------------------------------------------

'I2C-Initialisierungen
I2cinit

Config Twi = 100000                               ' Taktfrequenz 100 kBaud
Twcr = &B00000100                                 ' nur TWEN setzen
Twsr = 0                                          ' Status und Prescaler Register
Twbr = 152                                        ' Bit Rate Register, 72 = 100kHz   152 = 50kHz(0 bis 255)
Config I2cdelay = 40

'Initialisierung des LCD
Gosub Lcd_init

'Testaufrufe
Call Lcd_write( "    *!HELLO!*")
Wait 1
Gosub Lcd_gotoline_1
Call Lcd_write( " The launch of")
Gosub Lcd_gotoline_2
Call Lcd_write( "the psychrometer")

Time$ = "14:00:00"
Date$ = "23-07-17"

Wait 2
Gosub Lcd_cls

!rCall Lcd_cls

  Gosub Lcd_gotoline_2
  Call Lcd_write( "#")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "##")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "###")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "####")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "#####")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "######")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "#######")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "########")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "#########")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "##########")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "###########")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "############")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "#############")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "##############")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "###############")
  Waitms 170
  Gosub Lcd_cls
  Gosub Lcd_gotoline_2
  Call Lcd_write( "################")
  Waitms 190
  Gosub Lcd_cls

'------------------------------------------------------------------------------
' Programm - Hauptschleife
'------------------------------------------------------------------------------
Do

  Call Get_th(T , H)

  1_line_str = "          T:" + t_str + "C"  'собираем строку выводимую на lcd
  Gosub Lcd_gotoline_1
  Call Lcd_write(1_line_str)   'выводим строку на lcd

  1_line_strh = "          H:" + h_str + "%"   'собираем строку выводимую на lcd
  Gosub Lcd_gotoline_2
  Call Lcd_write(1_line_strh)   'выводим строку на lcd

  Gosub Lcd_gotoline_1
  Call Lcd_write(Time$)   'выводим строку на lcd
  Gosub Lcd_gotoline_2
  Call Lcd_write(Date$)   'выводим строку на lcd

  Wait 1


'  Toggle Led

Loop
'------------------------------------------------------------------------------
' Subroutinen
'------------------------------------------------------------------------------

Sub Lcd_write(byval Text As String)

   Dim Lcd_char As String * 1
   Dim Lcd_char_val As Byte

   'starte ?bertragung
   I2cstart
   I2cwbyte Addr_lcd_pcf_w

   Set Lcd_port_rs

   For I = 1 To Len(text)
     Lcd_char = Mid(text , I , 1)
     Lcd_char_val = Asc(lcd_char)
     Lcd_port_db7 = Lcd_char_val.7
     Lcd_port_db6 = Lcd_char_val.6
     Lcd_port_db5 = Lcd_char_val.5
     Lcd_port_db4 = Lcd_char_val.4
     I2cwbyte Lcd_port
     Gosub Lcd_pulse_e
     Lcd_port_db7 = Lcd_char_val.3
     Lcd_port_db6 = Lcd_char_val.2
     Lcd_port_db5 = Lcd_char_val.1
     Lcd_port_db4 = Lcd_char_val.0
     I2cwbyte Lcd_port
     Gosub Lcd_pulse_e
   Next

   Reset Lcd_port_db7
   Reset Lcd_port_db6
   Reset Lcd_port_db5
   Reset Lcd_port_db4
   Reset Lcd_port_rs

   I2cstop

End Sub

Sub Get_th(t As Byte , H As Byte)

 Count = 0
 Sensor_data = ""
 Set Dht_io_set                                         'делаем PD.6 выходом
 Reset Dht_put                                          'прижимаем шину к земле
 Waitms 25                                              'ждем не менее 18мс

 Set Dht_put                                            'отпускаем шину
 Waitus 40
 Reset Dht_io_set                                       'делаем PD.6 входом
 Waitus 40                                              'ждем 40 мкс
 If Dht_get = 1 Then                                    'если на нем по прежнему 1
    H = 1                                               'значит датчик не ответил
    Exit Sub                                            'выходим из подпрограммы
 End If

'если датчик ответил и прижал шину к земле продолжаем работу
  Waitus 80                                             'ждем еще 80 мкс
  If Dht_get = 0 Then                                   'если на линии по прежнему 0
    H = 2                                               'значит датчик сошел с ума
    Exit Sub                                            'выходим из подпрограммы
  End If

'если все нормально и датчик ответил правильно, тогда продолжаем

  While Dht_get = 1 : Wend                'ждем пока на шине появится 1

   Do                                     'начинаем принимать 40 бит данных
    While Dht_get = 0 : Wend              'ждем появления на шине 0
    Waitus 30                             'после появления 0 ждем 30мкс
     If Dht_get = 1 Then                  'если на шине 1
       Sensor_data = Sensor_data + "1"    'записываем в переменную эту единицу
       While Dht_get = 1 : Wend           'и ждем пока датчик отправит следующий бит
       Else                               'иначе, если там был 0
       Sensor_data = Sensor_data + "0"    'записываем этот 0 в переменную
    End If
    Incr Count                            'увеличиваем счетчик на 1
   Loop Until Count = 40                  'повторяем пока счетчик не досчитает до 40

   Set Dht_io_set
   Set Dht_put

'начинаем раскладывать полученные данные

   Tmp_str8 = Left(sensor_data , 8)                'берем левые 8 символов переменной
   H = Binval(tmp_str8)                            'это целая часть влажности
   h_str = str(h)  'делаем строковую переменную
   h_str = format(h_str,"  0")  'убираем незначащие нули

   Tmp_str8 = Mid(sensor_data , 17 , 8)            'вытаскиваем 8 символов из середины
   T = Binval(tmp_str8)                            'это целая часть температуры
   t_str = str(t)  'делаем строковую переменную
   t_str = format(t_str,"  0")  'убираем незначащие нули


   Tmp_str8 = Right(sensor_data , 8)               'правые 8 символов
   Crc = Binval(tmp_str8)                          'проверочные данные

'проверка контрольной суммы

   Mybyte = T + H                      'складываем значение температуры и влажности
   If Mybyte <> Crc Then               'если контрольная сумма не сошлась
      H = 3                            'значит полученные данные не верны
   End If

End Sub

Sub Ds1302_write(byval Clockcommand As Byte , Clockbyte As Byte)

   Config Ds1302_io_port = Output

   Set Ds1302_clock

   Reset Ds1302_io

   Set Ds1302_enable

   Reset Ds1302_clock

   Reset Ds1302_enable

   Waitus 5

   Set Ds1302_enable

   Waitus 5                                                 'tcc =4us, CE to clock setup time

   Shiftout Ds1302_io_port , Ds1302_clock , Clockcommand , 3

   Shiftout Ds1302_io_port , Ds1302_clock , Clockbyte , 3

   Reset Ds1302_clock

   Waitus 5

   Reset Ds1302_enable

   Waitus 5

End Sub

Function Ds1302_read(byval Clockcomand As Byte) As Byte

   Dim Readbyte As Byte

   Config Ds1302_io_port = Output

   Set Ds1302_clock

   Set Ds1302_io

   Set Ds1302_enable

   Reset Ds1302_clock

   Reset Ds1302_enable

   Waitus 5

   Set Ds1302_enable

   Waitus 5                                                 'tcc =4us, CE to clock setup time

   Shiftout Ds1302_io_port , Ds1302_clock , Clockcomand , 3

   Config Ds1302_io_port = Input

   Set Ds1302_clock

   Reset Ds1302_io

   Set Ds1302_enable

   Shiftin Ds1302_io , Ds1302_clock , Readbyte , 2

   Reset Ds1302_enable

   Rotate Readbyte , Left , 1

   Waitus 5

   Ds1302_read = Readbyte

End Function

Getdatetime:

   _sec = Ds1302_read(&H81)

   _min = Ds1302_read(&H83)

   _hour = Ds1302_read(&H85)

   _day = Ds1302_read(&H87)

   _month = Ds1302_read(&H89)

   _year = Ds1302_read(&H8d)

  _sec = Makedec(_sec)
  _min = Makedec(_min)
  _hour = Makedec(_hour)
  _day = Makedec(_day)
  _month = Makedec(_month)
  _year = Makedec(_year)

Return

Setdate:

   _day = Makebcd(_day)
   Ds1302_write &H86 , _year

   _month = Makebcd(_month)
   Ds1302_write &H88 , _month

   _year = Makebcd(_year)
   Ds1302_write &H8C , _year

Return

Settime:

   _hour = Makebcd(_hour)
   Ds1302_write &H84 , _hour

   _min = Makebcd(_min)
   Ds1302_write &H82 , _min

   _sec = Makebcd(_sec)
   Ds1302_write &H80 , _sec

ReturnSettime:

   _hour = Makebcd(_hour)
   Ds1302_write &H84 , _hour

   _min = Makebcd(_min)
   Ds1302_write &H82 , _min

   _sec = Makebcd(_sec)
   Ds1302_write &H80 , _sec

Return


'------------------------------------------------------------------------------
' LCD-GOSubs
'------------------------------------------------------------------------------

Lcd_init:

   I2cstart                                       ' START-Sequenz senden
   I2cwbyte Addr_lcd_pcf_w                        'Adresse vom PCF
   Lcd_port = 0
   I2cwbyte Lcd_port                              'alles l?schen


   '8-Bit setzen, 3 mal DB4 und 5 mit nachfolgendem E-Pulse
   Set Lcd_port_db4
   Set Lcd_port_db5
   For I = 1 To 3
      I2cwbyte Lcd_port
      Gosub Lcd_pulse_e
   Next I
   Reset Lcd_port_db4
   Reset Lcd_port_db5


   '4-Bit Datamode setzen, DB5
   Set Lcd_port_db5
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db5

   '4-Bit Data transfer setzen, DB5, danach DB7
   Set Lcd_port_db5
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db5
   Set Lcd_port_db7
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db7


   'Display und Cursor anschalten, 0-Polse, dann DB6 und DB7
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Set Lcd_port_db6
   Set Lcd_port_db7
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db6
   Reset Lcd_port_db7

   'CLS, DB4
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Set Lcd_port_db4
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db4

   'cursor setzen, DB5 und DB6
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Set Lcd_port_db5
   Set Lcd_port_db6
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db5
   Reset Lcd_port_db6

   'Beleuchtung ausschalten
   Lcd_port_bel = Lcd_beleuchtung
   I2cwbyte Lcd_port

   I2cstop

Return

Lcd_pulse_e:
   Set Lcd_port_e
   I2cwbyte Lcd_port
   Reset Lcd_port_e
   I2cwbyte Lcd_port
Return

Lcd_gotoline_1:
   I2cstart
   I2cwbyte Addr_lcd_pcf_w
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Set Lcd_port_db5
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db5
   I2cstop
Return

Lcd_gotoline_2:
   I2cstart
   I2cwbyte Addr_lcd_pcf_w
   Set Lcd_port_db7
   Set Lcd_port_db6
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Reset Lcd_port_db7
   Reset Lcd_port_db6
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   I2cstop
Return

Lcd_cls:
   I2cstart
   I2cwbyte Addr_lcd_pcf_w
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   Set Lcd_port_db4
   I2cwbyte Lcd_port
   Gosub Lcd_pulse_e
   I2cstop
Return


End

Сорри за код, как сказать разбираюсь, пробую, экспериментирую, может где и интервалы некорректные.

DS1302 подключены следующим образом:
PortC.6   ->   RST
PortC.5   ->   DAT
PortC.4   ->   CLK

DHT11 на порту PortD.6

По ссылке используемая библиотека для DS1302 используемая в данном проекте.
ds1302clock.lib

Если есть у кого возможность помочь разобраться почему как сказать часы не идут, или ещё какие дополнения, замечания будут в целом по данной конструкции, буду очень признателен.

Заранее всем благодарен!

Отредактировано artur (2017-07-23 15:20:09)

0

2

Как все запутанно...
В примерах (папка SAMPLES в пакете Bascom) есть рабочий код для 1307.
Я, обычно, включаю секундный импульс SQW на 1307  и по прерыванию читаю время-дату и вывожу на экран.
В остальное время МК может быть занят другой работой...

ЗЫ Если МК постоянно что-то ждет ( использована команда Wait ) зачем ему 16Мгц?
Как объяснили мне гуру этого форума, частота 16Мгц на гране рабочей возможности МК AVR.

Отредактировано pavel1969 (2017-07-23 18:38:20)

0

3

pavel1969, часы 1302, а не 1307
А 16 мГц - кварц такой, да не проблема, можно и от внутреннего RC тактироваться, это не принципиально
И когда тактируется не от внешнего кварца при работе с UART в терминале бог весь что, изменение скорости не влияет :( По этому и кварц

Отредактировано artur (2017-07-23 20:01:35)

0

4

artur написал(а):

pavel1969, часы 1302, а не 1307

Не-досмотрел...  :confused:

0

5

А случайно нет ни у кого рабочего кода для RTC DS1302 ? Желательно с выводом на дисплей 1602 по I2C

0


Вы здесь » Программирование ATMEL в BASCOM. » Исходники » Очередные часы с термометром и гигрометром