<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=58&amp;t=9162&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-11-09T20:34:12+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=58&amp;t=9162&amp;mode</id>
<entry>
<author><name><![CDATA[grzeszal]]></name></author>
<updated>2014-11-09T20:32:36+01:00</updated>
<published>2014-11-09T20:32:36+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103055#p103055</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103055#p103055"/>
<title type="html"><![CDATA[Re: Atmega32 i RTC DS1302 - problem]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103055#p103055"><![CDATA[
..ano nie odznaczyłem. dzięki za pomoc<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2449">grzeszal</a> — 9 lis 2014, o 20:32</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[kicajek]]></name></author>
<updated>2014-11-09T20:20:31+01:00</updated>
<published>2014-11-09T20:20:31+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103052#p103052</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103052#p103052"/>
<title type="html"><![CDATA[Re: Atmega32 i RTC DS1302 - problem]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103052#p103052"><![CDATA[
Witam<br /><div class="quotetitle">grzeszal napisał(a):</div><div class="quotecontent"><br />...nie chce mi działać z Atmegą32<br /></div><br />... a JTAG'a odznaczyłeś? - on może psuć PORTC<br /><br />Pozdr.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=826">kicajek</a> — 9 lis 2014, o 20:20</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[grzeszal]]></name></author>
<updated>2014-11-09T20:34:12+01:00</updated>
<published>2014-11-09T18:23:03+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103034#p103034</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103034#p103034"/>
<title type="html"><![CDATA[Atmega32 i RTC DS1302 - problem]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9162&amp;p=103034#p103034"><![CDATA[
Na początku chciałbym wspomnieć że jestem początkującym, zarówno w przygodzie z elektroniką jak i z programowaniem w języku C. Proszę więc o wyrozumiałość.  Od jakiegoś czasu piszę program, który będzie rejestrował czas zadziałania czujnika, będzie zapisywał datę i godzinę jego zadziałania do pamięci EEPROM. Pierwotnie program pisałem na procesor ATMEGA328, ale ze względu na potrzebę wykorzystania dużej ilości wejść dla czujników (najprawdopodobniej forezystory) zmieniłem procesor na ATMEGA32. Jak RTC wykorzystuje układ DS1302. Z Atmegą328 działa mi bez problemu na poniższym kodzie, natomiast nie chce mi działać z Atmegą32. Poniżej załączam kody źródłowe. Obsługa wyświetlacza działa bez zarzutu - problem jest z biblioteką do obsługi układu DS1302.<br />Przy Atmedze32 dostaję dziwne odczyty typu data: 45/45/20145, a godzina np. 45:82:67<br /><br /><br />main.c<br />[syntax=c]/*<br /> * main.c<br /> *<br /> *  Created on: 18-11-2013<br /> *      Author: Grzegorz<br /> */<br />#include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;avr/eeprom.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;util/atomic.h&gt;<br /><br />#include &quot;HD44780.h&quot;<br />#include &quot;main.h&quot;<br />#include &quot;rtc2.h&quot;<br /><br /><br />int main( void ){<br /><br />//inicjalizacja<br />LCD_Initalize();<br />rtc2_init();<br />//key_init();<br />soft_timer_init();<br /><br />//menu powitalne<br />LCD_Clear();<br />LCD_Home();<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;xxxx ver.1.0&quot;);<br />_delay_ms(2000);<br />LCD_GoTo(0,1);<br />LCD_WriteText(&quot;Produkt:grzeszal&quot;);<br />_delay_ms(2000);<br /><br />sei();<br /><br />while (1)<br />{<br /><br /><br />//wejscie wmenu ustawien<br />if( !KEY_WYBOR )<br />{<br />_delay_ms(200);<br />Ustawienia();<br />}<br /><br /><br />//wyswietlanie biezacego czasu<br />if( !Timer1 ) {<br />Timer1 = 1000;<br />LCDczas();<br />}<br /><br /><br />}<br />}<br /><br /><br />//ustawienia dla wejsc obslugujacych przyciski sterujace<br />void key_init(void)<br />{<br />//porty jako wejscie<br />PW_DDR &amp;= ~(1&lt;&lt;PW_WYBOR);<br />PP_DDR &amp;= ~(1&lt;&lt;PP_PLUS);<br />PM_DDR &amp;= ~(1&lt;&lt;PM_MINUS);<br />//stan wysoki na wejsciu<br />PW_PORT |= (1&lt;&lt;PW_WYBOR);<br />PP_PORT |= (1&lt;&lt;PP_PLUS);<br />PM_PORT |= (1&lt;&lt;PM_MINUS);<br />}<br /><br /><br />//aktualny czas wyswietlany na wyswietlaczu LCD<br />void LCDczas(void)<br />{<br /><br />char buf1&#91;64&#93; = {0};<br />char buf2&#91;64&#93; = {0};<br />rtc2_update(RTC2_VALUE);<br /><br />    sprintf(buf1, &quot;%02i/%02i/20%02i &quot;,<br />        RTC2_VALUE-&gt;date, RTC2_VALUE-&gt;month, RTC2_VALUE-&gt;year);<br />    sprintf(buf2, &quot;%02i:%02i:%02i &quot;,<br />    RTC2_VALUE-&gt;hours, RTC2_VALUE-&gt;minutes, RTC2_VALUE-&gt;seconds);<br />LCD_Clear();<br />LCD_GoTo(0,0);<br />LCD_WriteText(buf1);<br />LCD_GoTo(0,1);<br />LCD_WriteText(buf2);<br /><br />}<br /><br />//menu ustawienia - wybor ustawienia daty lub czujnikow<br />void Ustawienia(void)<br />{<br />int i=0;<br />while (1)<br />{<br />if (( !KEY_PLUS ) &amp;&amp; ( !KEY_MINUS ))<br />{<br />break;<br />}<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;Ustawienia      &quot;);<br />if( !KEY_PLUS )<br />{<br />_delay_ms(200);<br />i++;<br />}<br />if( !KEY_MINUS )<br />{<br />_delay_ms(200);<br />i--;<br />}<br />if (i&lt;0) i=2;<br />if (i&gt;2) i=1;<br />    switch(i)<br />    {<br />case 0:<br />LCD_GoTo(0,1);<br />LCD_WriteText(&quot;................&quot;);<br />break;<br /><br />        case 1:<br />    LCD_GoTo(0,1);<br />    LCD_WriteText(&quot;Czujniki        &quot;);<br />    break;<br /><br />        case 2:<br />    LCD_GoTo(0,1);<br />    LCD_WriteText(&quot;Data/godzina    &quot;);<br />    break;<br />    }<br />    if( !KEY_WYBOR )<br />    {<br />    switch(i)<br />    {<br />case 0:<br />_delay_ms(400);<br />break;<br /><br />case 1:<br />//czujnik();<br />_delay_ms(400);<br />break;<br /><br />case 2:<br />ustawCzas();<br />_delay_ms(400);<br />break;<br />    }<br />    }<br />}<br />}<br /><br /><br />//ustawianie czasu<br />void ustawCzas(void)<br />{<br />char lcd&#91;10&#93; = {0};<br />int mRok;<br />uint8_t mMies;<br />uint8_t mDzien;<br />int mGodz;<br />int mMin;<br />rtc2_update(RTC2_VALUE);<br />    mRok =  RTC2_VALUE-&gt;year;<br />    mMies = RTC2_VALUE-&gt;month;<br />    mDzien = RTC2_VALUE-&gt;date;<br />    mGodz = RTC2_VALUE-&gt;hours;<br />    mMin = RTC2_VALUE-&gt;minutes;<br />    LCD_Clear();<br />_delay_ms(400);<br />while ( KEY_WYBOR )<br />{<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;Ustaw Rok&quot;);<br />if( !KEY_PLUS )<br />{<br />_delay_ms(200);<br />mRok++;<br />}<br />if( !KEY_MINUS )<br />{<br />_delay_ms(200);<br />mRok--;<br />}<br />if (mRok&lt;0) mRok=90;<br />if (mRok&gt;90) mRok=0;<br />sprintf(lcd, &quot;20%02i &quot;,mRok);<br />LCD_GoTo(0,1);<br />LCD_WriteText(lcd);<br />}<br /><br />    LCD_Clear();<br />_delay_ms(400);<br />while ( KEY_WYBOR )<br />{<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;Ustaw Miesiac&quot;);<br />if( !KEY_PLUS )<br />{<br />_delay_ms(200);<br />mMies++;<br />}<br />if( !KEY_MINUS )<br />{<br />_delay_ms(200);<br />mMies--;<br />}<br />if (mMies&lt;1) mMies=12;<br />if (mMies&gt;12) mMies=1;<br />sprintf(lcd, &quot;%02i &quot;,mMies);<br />LCD_GoTo(0,1);<br />LCD_WriteText(lcd);<br />}<br /><br />    LCD_Clear();<br />_delay_ms(400);<br />while ( KEY_WYBOR )<br />{<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;Ustaw Dzien&quot;);<br />if( !KEY_PLUS )<br />{<br />_delay_ms(200);<br />mDzien++;<br />}<br />if( !KEY_MINUS )<br />{<br />_delay_ms(200);<br />mDzien--;<br />}<br />if (mDzien&lt;1) mDzien=dzienMiesiac&#91;mMies-1&#93;;<br />if (mDzien&gt;dzienMiesiac&#91;mMies-1&#93;) mDzien=1;<br />sprintf(lcd, &quot;%02i &quot;,mDzien);<br />LCD_GoTo(0,1);<br />LCD_WriteText(lcd);<br />}<br /><br />    LCD_Clear();<br />_delay_ms(400);<br />while ( KEY_WYBOR )<br />{<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;Ustaw Godzine&quot;);<br />if( !KEY_PLUS )<br />{<br />_delay_ms(200);<br />mGodz++;<br />}<br />if( !KEY_MINUS )<br />{<br />_delay_ms(200);<br />mGodz--;<br />}<br />if (mGodz&lt;0) mGodz=23;<br />if (mGodz&gt;23) mGodz=0;<br />sprintf(lcd, &quot;%02i &quot;,mGodz);<br />LCD_GoTo(0,1);<br />LCD_WriteText(lcd);<br />}<br /><br />    LCD_Clear();<br />_delay_ms(400);<br />while ( KEY_WYBOR )<br />{<br />LCD_GoTo(0,0);<br />LCD_WriteText(&quot;Ustaw Minuty&quot;);<br />if( !KEY_PLUS )<br />{<br />_delay_ms(200);<br />mMin++;<br />}<br />if( !KEY_MINUS )<br />{<br />_delay_ms(200);<br />mMin--;<br />}<br />if (mMin&lt;0) mMin=59;<br />if (mMin&gt;59) mMin=0;<br />sprintf(lcd, &quot;%02i &quot;,mMin);<br />LCD_GoTo(0,1);<br />LCD_WriteText(lcd);<br />}<br /><br />ATOMIC_BLOCK(ATOMIC_RESTORESTATE)<br />{<br /><br />RTC2_VALUE-&gt;seconds = 0;<br />RTC2_VALUE-&gt;minutes = mMin;<br />RTC2_VALUE-&gt;hours = mGodz;<br />RTC2_VALUE-&gt;date = mDzien;<br />RTC2_VALUE-&gt;month = mMies;<br />RTC2_VALUE-&gt;year = mRok;<br /><br />rtc2_preset(RTC2_VALUE);<br />}<br />}<br /><br /><br />// funkcja zapisująca czas w zmiennej buf w formacie DD/MM/RR GG:MM<br />void Czas(void)<br />{<br />rtc2_update(RTC2_VALUE);<br />    sprintf(buf, &quot;%02i/%02i/%02i %02i:%02i:%02i&quot;,<br />    RTC2_VALUE-&gt;date,<br />    RTC2_VALUE-&gt;month,<br />    RTC2_VALUE-&gt;year,<br />    RTC2_VALUE-&gt;hours,<br />    RTC2_VALUE-&gt;minutes,<br />    RTC2_VALUE-&gt;seconds);<br />}<br /><br /><br /><br />void soft_timer_init(void)<br />{<br /><br />//Atmega32<br />TCCR0 |= (1&lt;&lt;WGM01);   // tryb CTC<br />    TCCR0 |= (1&lt;&lt;CS00);    // bez prescalera<br />    OCR0 = 255;            // dodatkowy podział częstotliwości<br />    TIMSK |= (1&lt;&lt;OCIE0);   // zezwolenie na przerwanie Output Compare A Match Interrupt Enable<br /><br />}<br /><br /><br />ISR( TIMER0_COMP_vect ) {<br />uint16_t n;<br /><br />n = Timer1;//event to be exicuted every 4ms here<br />if (n) Timer1 = --n;<br />n = Timer2;//event to be exicuted every 4ms here<br />if (n) Timer2 = --n;<br />}[/syntax]<br /><br />main.h<br />[syntax=c]/*<br /> * main.h<br /> *<br /> *  Created on: 18-11-2013<br /> *      Author: Grzegorz<br /> */<br /><br />#ifndef MAIN_H_<br />#define MAIN_H_<br /><br />//definicja portu i pinow dla przyciskow sterujacych<br />#define PW_PORTPORTC<br />#define PW_PIN PINC<br />#define PW_DDR DDRC<br />#define PW_WYBOR PC3<br /><br />#define PP_PORTPORTC<br />#define PP_PIN PINC<br />#define PP_DDR DDRC<br />#define PP_PLUS  PC4<br /><br />#define PM_PORTPORTC<br />#define PM_PIN PINC<br />#define PM_DDR DDRC<br />#define PM_MINUS PC5<br /><br />//makro nie wcisnietego przycisku<br />#define KEY_WYBOR (PW_PIN &amp; (1&lt;&lt;PW_WYBOR))<br />#define KEY_PLUS (PP_PIN &amp; (1&lt;&lt;PP_PLUS))<br />#define KEY_MINUS (PM_PIN &amp; (1&lt;&lt;PM_MINUS))<br /><br /><br />//zmienne<br />char buf&#91;64&#93; = {0};<br />volatile uint16_t Timer1, Timer2;<br />static uint8_t dzienMiesiac&#91;&#93; = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };<br /><br />//funkcje<br />int main( void );<br />void LCDczas(void);<br />void Ustawienia(void);<br />void ustawCzas(void);<br />void Czas(void);<br />void soft_timer_init(void);<br />void key_init(void);<br /><br /><br />#endif /* MAIN_H_ */[/syntax]<br /><br />oraz pliki obsługi RTC<br />[syntax=c]#ifndef __RTC2_CONFIG_H__<br />#define __RTC2_CONFIG_H__<br />/*<br /> * bibloteka zostala zmodyfikowany do pracy w systemie 24 godzinnym (RTC2_FORMAT_24)<br /> */<br /><br />// if there is no configuration then apply some defaults<br />#ifndef RTC2_PORT<br /><br />// port where DS1302 is connected. currently only one port mode<br />// is supported, e.g. you should connect all lines from DS1302 <br />// to one port<br />#define RTC2_PORT PORTC<br />#define RTC2_PIN  PINC<br />#define RTC2_DDR  DDRC<br /><br />// DS1302 SCLK line<br />#define RTC2_CLK PC0<br />// DS1302 I/O line<br />#define RTC2_IO  PC1<br />// DS1302 CE line<br />#define RTC2_CE  PC2<br /><br />// memory read address range. write address = read address - 1<br />// make sure this matches your datasheet<br />#define RTC2_MEM_START 0xC1<br />#define RTC2_MEM_END 0xFD<br /><br />#endif<br /><br />// following defines disable/enable library features.<br />// to save some space you can disable unused functionality.<br /><br />// define global variable?<br />#ifndef RTC2_DEFAULT<br />#define RTC2_DEFAULT 1<br />#endif<br /><br />// enable clock read functions?<br />#ifndef RTC2_READ<br />#define RTC2_READ 1<br />#endif<br /><br />// enable timestamp<br />#ifndef RTC2_TIMESTAMP<br />#define RTC2_TIMESTAMP 1<br />#endif<br /><br />// enable clock write functions?<br />#ifndef RTC2_WRITE<br />#define RTC2_WRITE 1<br />#endif<br /><br />// enable burst mode? (reading in series of sequential bytes)<br />#ifndef RTC2_BURST<br />#define RTC2_BURST 1<br />#endif<br /><br />// enable RAM utilities? (write to autonomous RAM in DS1302)<br />#ifndef RTC2_RAM<br />#define RTC2_RAM 1<br />#endif<br /><br />// RAM strings functions puts/gets. RTC2_RAM must be enabled to use this.<br />#ifndef RTC2_RAM_STRINGS<br />#define RTC2_RAM_STRINGS 1<br />#endif<br /><br />// enable utility functions: clock halt, charger and protection settings<br />#ifndef RTC2_UTILITY<br />#define RTC2_UTILITY 1<br />#endif<br /><br />// a macro for getting available memory size. not used anywhere,<br />// maybe can be used in program<br />#define RTC2_MEM_SIZE ((RTC2_MEM_START - RTC2_MEM_END) / 2 + 1)<br /><br />#endif[/syntax]<br /><br />[syntax=c]// vim: foldmethod=marker<br />#ifndef __RTC2_H__<br />#define __RTC2_H__<br /><br />#include &lt;stdint.h&gt;<br />#include &lt;stddef.h&gt;<br />#include &quot;rtc2_config.h&quot;<br /><br />// Clock formats {{{<br />#define RTC2_FORMAT_AM 0x80<br />#define RTC2_FORMAT_PM 0xA0<br />#define RTC2_FORMAT_24 0x00<br />// }}}<br /><br />// Available fields for using with rtc2_preset, rtc2_set,<br />// rtc2_update, rtc2_get functions {{{<br />#define RTC2_SECONDS_FIELD   0x01<br />#define RTC2_MINUTES_FIELD   0x02<br />#define RTC2_HOURS_FIELD     0x04<br />#define RTC2_DATE_FIELD      0x08<br />#define RTC2_MONTH_FIELD     0x10<br />#define RTC2_WDAY_FIELD      0x20<br />#define RTC2_YEAR_FIELD      0x40<br /><br />#define RTC2_ALL_FIELDS      0x7F // all fields mean update/preset all above<br />// }}}<br /><br />// Charger flags. See datasheet for details. {{{<br />#define RTC2_CHARGER_DISABLE  0x0<br />#define RTC2_CHARGER_ENABLED  0xA0<br />#define RTC2_CHARGER_1_DIODES 0x08<br />#define RTC2_CHARGER_2_DIODES 0x04<br />#define RTC2_CHARGER_ROUTE_1  0x1<br />#define RTC2_CHARGER_ROUTE_2  0x2<br />#define RTC2_CHARGER_ROUTE_3  0x3<br />// }}}<br /><br />// Timestamp base date {{{<br />#if RTC2_TIMESTAMP<br />#define RTC2_BASE_TIMESTAMP 946684800<br />#endif<br />// }}}<br /><br />// You can disable clock and use just RAM/utility functions,<br />// but why do you need DS1302 then?<br /><br />// Clock definitions {{{<br />#if RTC2_READ || RTC2_WRITE<br /><br />typedef struct {<br />  // time<br />  uint8_t seconds;<br />  uint8_t hours;<br />  uint8_t minutes;<br /><br />  // date<br />  uint8_t wday;<br />  uint8_t date;<br />  uint8_t month;<br />  uint8_t year;<br /><br />} rtc2_datetime_t;<br /><br />typedef rtc2_datetime_t* rtc2_datetime;<br /><br />#endif<br />// }}}<br /><br />void rtc2_init(void);<br /><br />// Clock reading/writing functions will use burst mode<br />// only if you read/write all fields and RTC2_BURST is non zero<br /><br />// Write (preset) functions {{{<br />#if RTC2_WRITE<br />void rtc2_preset(rtc2_datetime src);<br />void rtc2_set(rtc2_datetime src, uint8_t fields);<br />#endif<br />// }}}<br /><br />// Read (update) functions {{{<br />#if RTC2_READ<br />// gets all clock value from DS1302<br />void rtc2_update(rtc2_datetime dst);<br />// gets specified fields from DS1302. fields are given<br />// as bitwise concatenation of RTC2_*_FIELD constants.<br />// providing RTC2_ALL_FIELDS is effectively the same<br />// as rtc2_update.<br />void rtc2_get(rtc2_datetime dst, uint8_t fields);<br /><br />// Timestamp conversion functions {{{<br />#if RTC2_TIMESTAMP<br />// **WARNING1**: IT IS IN LOCAL TIMEZONE<br />// **WARNING2**: Because we have unsigned chars everywhere<br />// and today is 2014 after all, base line for calculation<br />// is 2000/1/1 00:00:00. E.g. all dates are treated like they're<br />// after the this date.<br />//<br />// returns UNIX timestamp (since 1970/1/1 00:00:00)<br />// month starts from 1, years are two digits since 2000<br />uint32_t rtc2_mktime(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t date, uint8_t month, uint8_t year);<br />// wrapper passing rtc2_datetime fields to rtc2_mktime<br />uint32_t rtc2_timestamp(rtc2_datetime src);<br />// populates rtc2_datetime from timestamp<br />// will return 0 if timestamp is &lt; RTC2_BASE_TIMESTAMP which is 1st January 2000<br />uint8_t rtc2_localtime(rtc2_datetime dst, uint32_t timestamp);<br />#endif<br />//}}}<br /><br />#endif<br />// }}}<br /><br />// RAM access functions {{{<br />#if RTC2_RAM<br /><br />// offset in RAM functions is relative to RTC2_MEM_START.<br />// do not pass actual address.<br />// whenever those functions see that target have offset not fiting<br />// into memory range they'll silently cancel.<br />//<br />// functions operating on memory chunks verify both first byte (offset)<br />// and last byte (offset + size).<br />//<br />// also those functions will work in burst mode only if offset is 0<br />// that is reading from beginning of memory and RTC2_BURST is non-zero.<br /><br />void rtc2_mem_write_byte(uint8_t offset, uint8_t value);<br />uint8_t rtc2_mem_read_byte(uint8_t offset);<br /><br />void rtc2_mem_write(uint8_t offset, size_t size, const void *src);<br />void rtc2_mem_read(uint8_t offset, size_t size, void *dst);<br /><br />/// RAM string helpers {{{<br />#if RTC2_RAM_STRINGS<br />void rtc2_mem_puts(uint8_t offset, const char *src);<br />void rtc2_mem_gets(uint8_t offset, size_t maxsize, char *dst);<br />#endif<br />// }}}<br /><br />#endif<br />// }}}<br /><br />// NOTE: true_false are exactly 1 bit, if you'll pass something else<br />// it can result in undesired effect.<br /><br />// Utility functions {{{<br />#if RC2_UTILITY<br />// get trickle charger state. see RTC2_CHARGER_*<br />// constants above and datasheet for possible results.<br />uint8_t rtc2_get_charger(void);<br />// sets trickle charger state. see datasheet.<br />void rtc2_set_charger(uint8_t flags);<br /><br />// are clock/RAM values write-protected?<br />uint8_t rtc2_halt(void);<br />// enables/disables clock/RAM write-protection<br />void rtc2_set_halt(uint8_t true_false);<br /><br />// sets/gets clock setting protection<br />uint8_t rtc2_protection(void);<br />void rtc2_set_protection(uint8_t true_false);<br />#endif<br />// }}}<br /><br />// Default global variable (actually initialized pointer) {{{<br />#if RTC2_DEFAULT &amp;&amp; (RTC2_READ || RTC2_WRITE)<br />volatile rtc2_datetime RTC2_VALUE;<br />#endif<br />// }}}<br /><br />#endif[/syntax]<br /><br />[syntax=c]// vim: foldmethod=marker<br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br /><br />#include &quot;rtc2.h&quot;<br /><br />#if RTC2_RAM_STRINGS<br />#include &lt;string.h&gt;<br />#endif<br /><br />// Registers addresses from datasheet {{{<br />#define RTC2_SECONDS_READ  0x81<br />#define RTC2_SECONDS_WRITE 0x80<br /><br />#define RTC2_MINUTES_READ  0x83<br />#define RTC2_MINUTES_WRITE 0x82<br /><br />#define RTC2_HOURS_READ  0x85<br />#define RTC2_HOURS_WRITE 0x84<br /><br />#define RTC2_DATE_READ  0x87<br />#define RTC2_DATE_WRITE 0x86<br /><br />#define RTC2_MONTH_READ  0x89<br />#define RTC2_MONTH_WRITE 0x88<br /><br />#define RTC2_WDAY_READ  0x8B<br />#define RTC2_WDAY_WRITE 0x8A<br /><br />#define RTC2_YEAR_READ  0x8D<br />#define RTC2_YEAR_WRITE 0x8C<br /><br />#define RTC2_WP_READ  0x8F<br />#define RTC2_WP_WRITE 0x8E<br /><br />#define RTC2_CHARGER_READ  0x91<br />#define RTC2_CHARGER_WRITE 0x90<br /><br />#define RTC2_BURST_READ  0xBF<br />#define RTC2_BURST_WRITE 0xBE<br /><br />#define RTC2_BURST_MEM_READ  0xFF<br />#define RTC2_BURST_MEM_WRITE 0xFE<br />// }}}<br /><br />// RTC2 utility macro handling I/O {{{<br />#define RTC2_IO_OUTPUT (RTC2_DDR |= _BV(RTC2_IO))<br />#define RTC2_IO_INPUT (RTC2_DDR &amp;= ~_BV(RTC2_IO))<br />#define RTC2_IO_HIGH (RTC2_PORT |= _BV(RTC2_IO))<br />#define RTC2_IO_LOW (RTC2_PORT &amp;= ~_BV(RTC2_IO))<br /><br />#define RTC2_CLK_HIGH (RTC2_PORT |= _BV(RTC2_CLK))<br />#define RTC2_CLK_LOW (RTC2_PORT &amp;= ~_BV(RTC2_CLK))<br /><br />#define RTC2_CE_HIGH (RTC2_PORT |= _BV(RTC2_CE))<br />#define RTC2_CE_LOW (RTC2_PORT &amp;= ~_BV(RTC2_CE))<br /><br />#define RTC2_MEM_END_WRITE (RTC2_MEM_END - 1)<br />#define RTC2_MEM_START_WRITE (RTC2_MEM_START - 1)<br /><br />#define RTC2_MEM_READ_INVALID(x) ((x) &gt; RTC2_MEM_END || (x) &lt; RTC2_MEM_START)<br />#define RTC2_MEM_WRITE_INVALID(x) ((x) &gt; RTC2_MEM_END_WRITE || (x) &lt; RTC2_MEM_START_WRITE)<br /><br />#define RTC2_START_TRANSMISSION(kind) { rtc2_reset(); rtc2_write_byte(kind); } while(0)<br />#define RTC2_STOP_TRANSMISSION { RTC2_CE_LOW; RTC2_CLK_LOW; } while(0)<br />// }}}<br /><br />// Default global pointer memory {{{<br />#if RTC2_DEFAULT &amp;&amp; (RTC2_READ || RTC2__WRITE)<br />static rtc2_datetime_t rtc2_default = {0};<br />#endif<br />// }}}<br /><br />// Initializer. Configures I/O ports and maybe sets up global variable {{{<br />void rtc2_init(void){<br />  // set all pins to output<br />  RTC2_DDR |= _BV(RTC2_CE) | _BV(RTC2_CLK) | _BV(RTC2_IO);<br />  // and turn them off<br />  RTC2_PORT &amp;= ~(_BV(RTC2_CE) | _BV(RTC2_CLK) | _BV(RTC2_IO));<br /><br />  // initialize default global pointer if needed<br />#if RTC2_DEFAULT &amp;&amp; (RTC2_READ || RTC2__WRITE)<br />  RTC2_VALUE = &amp;rtc2_default;<br />#endif<br />}<br />// }}}<br /><br />// Utility stuff used to reset current transfer state {{{<br />static inline void rtc2_reset(void){<br />  RTC2_STOP_TRANSMISSION;<br />  RTC2_CE_HIGH;<br />}<br />// }}}<br /><br />// Low level write functions {{{<br /><br />// Routine used for pretty much any operation {{{<br />#if RTC2_READ || RTC2_WRITE ||RTC2_RAM || RTC2_UTILITY<br />static void rtc2_write_byte(uint8_t byte){<br />  uint8_t i;<br /><br />  RTC2_IO_OUTPUT;<br /><br />  for(i = 0; i &lt; 8; ++i){<br />    if(byte &amp; 1)<br />      RTC2_IO_HIGH;<br />    else<br />      RTC2_IO_LOW;<br /><br />    RTC2_CLK_LOW;<br />    _delay_us(2);<br />    RTC2_CLK_HIGH;<br />    _delay_us(2);<br />    byte &gt;&gt;= 1;<br />  }<br />}<br />#endif<br />// }}}<br /><br />// Write to register {{{<br />#if RTC2_WRITE || RTC2_RAM || RTC2_UTILITY<br /><br />static void rtc2_write(uint8_t reg, uint8_t val){<br />  RTC2_START_TRANSMISSION(reg);<br />  rtc2_write_byte(val);<br />  RTC2_STOP_TRANSMISSION;<br />}<br /><br />#endif<br />// }}}<br /><br />// }}}<br /><br />// Low level read functions {{{<br />#if RTC2_READ || RTC2_UTILITY || RTC2_RAM<br /><br />static uint8_t rtc2_read_byte(void){<br />  uint8_t i, ret = 0;<br /><br />  RTC2_IO_INPUT;<br /><br />  for(i = 0; i &lt; 8; ++i){<br />    RTC2_CLK_HIGH;<br />    _delay_us(2);<br />    RTC2_CLK_LOW;<br />    _delay_us(2);<br />    ret &gt;&gt;= 1;<br /><br />    if(bit_is_set(RTC2_PIN, RTC2_IO))<br />      ret |= _BV(7);<br />  }<br /><br />  return ret;<br />}<br /><br />static uint8_t rtc2_read(uint8_t reg){<br />  uint8_t ret;<br />  RTC2_START_TRANSMISSION(reg);<br />  ret = rtc2_read_byte();<br />  RTC2_STOP_TRANSMISSION;<br />  return ret;<br />}<br /><br />#endif<br />// }}}<br /><br />// Writing (presetting clock stuff) {{{<br />#if RTC2_WRITE<br /><br />void rtc2_preset(rtc2_datetime ptr){<br />  rtc2_set(ptr, RTC2_ALL_FIELDS);<br />}<br /><br />// encodes given values in BCD for sending to DS1302.<br />// we have to cut off higher parts to avoid accidently<br />// setting control bits.<br />static uint8_t rtc2_store_field(uint8_t field, uint8_t val){<br />  switch(field){<br />    case RTC2_SECONDS_WRITE:<br />    case RTC2_MINUTES_WRITE:<br />      val = (((val / 10) &lt;&lt; 4) &amp; 0x70) | (val % 10);<br />      break;<br />    case RTC2_HOURS_WRITE:<br />      val =  (((val / 10) &lt;&lt; 4) &amp; 0x30) | (val % 10);<br />      break;<br />    case RTC2_DATE_WRITE:<br />      val = (((val / 10) &lt;&lt; 4) &amp; 0x30) | (val % 10);<br />      break;<br />    case RTC2_MONTH_WRITE:<br />      val = (((val / 10) &lt;&lt; 4) &amp; 0x10) | (val % 10);<br />      break;<br />    case RTC2_WDAY_WRITE:<br />      val &amp;= 0x03;<br />      break;<br />    case RTC2_YEAR_WRITE:<br />      val = (((val / 10) &lt;&lt; 4) &amp; 0xF0) | (val % 10);<br />      break;<br />  }<br /><br />  return val;<br />}<br /><br />static void rtc2_set_val(uint8_t field, uint8_t val){<br />  rtc2_write(field, rtc2_store_field(field, val));<br />}<br /><br />void rtc2_set(rtc2_datetime ptr, uint8_t fields){<br />#if RTC2_BURST<br />  if(fields &amp; RTC2_ALL_FIELDS){<br />    RTC2_START_TRANSMISSION(RTC2_BURST_WRITE);<br /><br />    rtc2_write_byte(rtc2_store_field(RTC2_SECONDS_WRITE, ptr-&gt;seconds));<br />    rtc2_write_byte(rtc2_store_field(RTC2_MINUTES_WRITE, ptr-&gt;minutes));<br />    rtc2_write_byte(rtc2_store_field(RTC2_HOURS_WRITE, ptr-&gt;hours));<br />    rtc2_write_byte(rtc2_store_field(RTC2_DATE_WRITE, ptr-&gt;date));<br />    rtc2_write_byte(rtc2_store_field(RTC2_MONTH_WRITE, ptr-&gt;month));<br />    rtc2_write_byte(rtc2_store_field(RTC2_WDAY_WRITE, ptr-&gt;wday));<br />    rtc2_write_byte(rtc2_store_field(RTC2_YEAR_WRITE, ptr-&gt;year));<br />    rtc2_write_byte(0);<br /><br />    RTC2_STOP_TRANSMISSION;<br />  }else{<br />#endif<br />    if(fields &amp; RTC2_SECONDS_FIELD)<br />      rtc2_set_val(RTC2_SECONDS_WRITE, ptr-&gt;seconds);<br /><br />    if(fields &amp; RTC2_MINUTES_FIELD)<br />      rtc2_set_val(RTC2_MINUTES_WRITE, ptr-&gt;minutes);<br /><br />    if(fields &amp; RTC2_HOURS_FIELD)<br />      rtc2_set_val(RTC2_HOURS_WRITE, ptr-&gt;hours);<br /><br />    if(fields &amp; RTC2_DATE_FIELD)<br />      rtc2_set_val(RTC2_DATE_WRITE, ptr-&gt;date);<br /><br />    if(fields &amp; RTC2_MONTH_FIELD)<br />      rtc2_set_val(RTC2_MONTH_WRITE, ptr-&gt;month);<br /><br />    if(fields &amp; RTC2_WDAY_FIELD)<br />      rtc2_set_val(RTC2_WDAY_WRITE, ptr-&gt;wday);<br /><br />    if(fields &amp; RTC2_YEAR_FIELD)<br />      rtc2_set_val(RTC2_YEAR_WRITE, ptr-&gt;year);<br />#if RTC2_BURST<br />  }<br />#endif<br />}<br /><br />#endif<br />// }}}<br /><br />// High level decoding and reading (updating) functions {{{<br />#if RTC2_READ<br /><br />void rtc2_update(rtc2_datetime ptr){<br />  rtc2_get(ptr, RTC2_ALL_FIELDS);<br />}<br /><br />// decode values received from DS1302 from BCD to bin encoding.<br />// see datasheet for details. because some registers<br />// contain also control bits we cut off higher parts<br />// that are not data.<br />static uint8_t rtc2_parse_val(uint8_t field, uint8_t val){<br />  switch(field){<br />    case RTC2_SECONDS_READ:<br />    case RTC2_MINUTES_READ:<br />      val = (val &amp; 0x0F) + ((val &amp; 0x70) &gt;&gt; 4) * 10;<br />      break;<br />    case RTC2_HOURS_READ:<br />      val =  (val &amp; 0x0F) + ((val &amp; 0x30) &gt;&gt; 4) * 10;<br />      break;<br />    case RTC2_DATE_READ:<br />      val = (val &amp; 0x0F) + ((val &amp; 0x30) &gt;&gt; 4) * 10;<br />      break;<br />    case RTC2_MONTH_READ:<br />      val = (val &amp; 0x0F) + ((val &amp; 0x10) &gt;&gt; 4) * 10;<br />      break;<br />    case RTC2_WDAY_READ:<br />      val &amp;= 0x07;<br />      break;<br />    case RTC2_YEAR_READ:<br />      val = (val &amp; 0x0F) + ((val &amp; 0xF0) &gt;&gt; 4) * 10;<br />      break;<br />  }<br /><br />  return val;<br />}<br /><br />static uint8_t rtc2_get_val(uint8_t field){<br />  return rtc2_parse_val(field, rtc2_read(field));<br />}<br /><br />void rtc2_get(rtc2_datetime ptr, uint8_t fields){<br />#if RTC2_BURST<br />  if(fields &amp; RTC2_ALL_FIELDS){<br />    //uint8_t tmp;<br /><br />    RTC2_START_TRANSMISSION(RTC2_BURST_READ);<br /><br />    ptr-&gt;seconds = rtc2_parse_val(RTC2_SECONDS_READ, rtc2_read_byte());<br />    ptr-&gt;minutes = rtc2_parse_val(RTC2_MINUTES_READ, rtc2_read_byte());<br />    ptr-&gt;hours   = rtc2_parse_val(RTC2_HOURS_READ, rtc2_read_byte());<br /><br />    ptr-&gt;date    = rtc2_parse_val(RTC2_DATE_READ, rtc2_read_byte());<br />    ptr-&gt;month   = rtc2_parse_val(RTC2_MONTH_READ, rtc2_read_byte());<br />    ptr-&gt;wday    = rtc2_parse_val(RTC2_WDAY_READ, rtc2_read_byte());<br />    ptr-&gt;year    = rtc2_parse_val(RTC2_YEAR_READ, rtc2_read_byte());<br /><br />    RTC2_STOP_TRANSMISSION;<br />  }else{<br />#endif<br />    if(fields &amp; RTC2_SECONDS_FIELD)<br />      ptr-&gt;seconds = rtc2_get_val(RTC2_SECONDS_READ);<br /><br />    if(fields &amp; RTC2_MINUTES_FIELD)<br />      ptr-&gt;minutes = rtc2_get_val(RTC2_MINUTES_READ);<br /><br />    if(fields &amp; RTC2_HOURS_FIELD){<br />      ptr-&gt;hours = rtc2_get_val(RTC2_HOURS_READ);<br />    }<br /><br />    if(fields &amp; RTC2_DATE_FIELD)<br />      ptr-&gt;date = rtc2_get_val(RTC2_DATE_READ);<br /><br />    if(fields &amp; RTC2_MONTH_FIELD)<br />      ptr-&gt;month = rtc2_get_val(RTC2_MONTH_READ);<br /><br />    if(fields &amp; RTC2_WDAY_FIELD)<br />      ptr-&gt;wday = rtc2_get_val(RTC2_WDAY_READ);<br /><br />    if(fields &amp; RTC2_YEAR_FIELD)<br />      ptr-&gt;year = rtc2_get_val(RTC2_YEAR_READ);<br />#if RTC2_BURST<br />  }<br />#endif<br />}<br /><br />// UNIX timestamp utilities {{{<br />#if RTC2_TIMESTAMP<br /><br />// not exactly tzdata but will do<br />static uint8_t rtc2_monthes&#91;&#93; = {<br />  31, 28, 31,<br />  30, 31, 30,<br />  31, 31, 30,<br />  31, 30, 31<br />};<br /><br />uint32_t rtc2_mktime(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t date, uint8_t month, uint8_t year){<br />  uint32_t ret = RTC2_BASE_TIMESTAMP; // 1st January 2000, midnight<br /><br />  ret += seconds;<br />  ret += minutes * 60L;<br />  ret += hours   * 60L * 60;<br /><br />  --month;<br /><br />  if(year) // a special case for base timestamp<br />    date += (year - 1) / 4;<br />  else<br />    --date;<br /><br />  for(seconds = 0; seconds &lt; month; ++seconds)<br />    ret += rtc2_monthes&#91;seconds&#93; * 24L * 60 * 60;<br /><br />  if(month &gt; 1 &amp;&amp; year % 4 == 0)<br />    ++date;<br /><br />  ret += date * 24L * 60 * 60;<br />  ret += year * 365L * 24 * 60 * 60;<br /><br />  return ret;<br />}<br /><br />uint32_t rtc2_timestamp(rtc2_datetime src){<br /><br /><br />  return rtc2_mktime(<br />      src-&gt;seconds, src-&gt;minutes, src-&gt;hours,<br />      src-&gt;date,    src-&gt;month,   src-&gt;year<br />  );<br />}<br /><br />// will return 0 if timestamp is older tha RTC2_BASE_TIMESTAMP<br />// which is 1st January 2000<br /><br />uint8_t rtc2_localtime(rtc2_datetime dst, uint32_t timestamp){<br />  uint16_t i, y;<br /><br />  if(timestamp &lt; RTC2_BASE_TIMESTAMP)<br />    return 0;<br /><br />  timestamp -= RTC2_BASE_TIMESTAMP;<br /><br />  dst-&gt;seconds = timestamp % 60;<br />  timestamp /= 60;<br />  dst-&gt;minutes = timestamp % 60;<br />  timestamp /= 60;<br />  dst-&gt;hours = timestamp % 24;<br />  timestamp /= 24;<br />  dst-&gt;wday = (timestamp + 6) % 7; // because 1st January 2000 is Saturday add 6<br /><br />  for(y = 0; timestamp; ++y){<br />    i = 365 + (y % 4 == 0);<br /><br />    if(timestamp &lt; i)<br />      break;<br /><br />    timestamp -= i;<br />  }<br /><br />  dst-&gt;year = y;<br /><br />  ++timestamp;<br /><br />  for(i = 0; timestamp &gt; rtc2_monthes&#91;i&#93;; ++i){<br />    if(i == 1 &amp;&amp; y % 4 == 0){<br />      if(timestamp &gt; 29)<br />        timestamp -= 1;<br />      else<br />        break;<br />    }<br /><br />    timestamp -= rtc2_monthes&#91;i&#93;;<br />  }<br /><br />  dst-&gt;month = i + 1;<br />  dst-&gt;date = timestamp;<br /><br />  return 1;<br />}<br /><br />#endif<br />// }}}<br /><br />#endif<br />// }}}<br /><br />// RAM access {{{<br />#if RTC2_RAM<br /><br />// RAM has same access method, just different address<br />void rtc2_mem_write_byte(uint8_t offset, uint8_t val){<br />  offset += RTC2_MEM_START_WRITE;<br /><br />  // check for addres validity<br />  if(RTC2_MEM_WRITE_INVALID(offset))<br />    return; // kind of panic here or something<br /><br />  rtc2_write(offset, val);<br />}<br /><br />uint8_t rtc2_mem_read_byte(uint8_t offset){<br />  offset += RTC2_MEM_START;<br />  <br />  if(RTC2_MEM_READ_INVALID(offset))<br />    return 0;<br /><br />  return rtc2_read(offset);<br />}<br /><br />void rtc2_mem_write(uint8_t offset, size_t size, const void *buffer){<br />  offset += RTC2_MEM_START_WRITE;<br /><br />  // check that first byte is valid *and* last byte is valid too<br />  // (hence whole chunk fits)<br />  if(RTC2_MEM_WRITE_INVALID(offset) || RTC2_MEM_WRITE_INVALID(offset + size * 2))<br />    return;<br /><br />#if RTC2_BURST<br />  if(size &gt; 2 &amp;&amp; offset == RTC2_MEM_START_WRITE){<br />    RTC2_START_TRANSMISSION(RTC2_BURST_MEM_WRITE);<br /><br />    for(;size &gt; 0; offset += 2, --size, ++buffer)<br />      rtc2_write_byte(*(uint8_t*)buffer);<br /><br />    RTC2_STOP_TRANSMISSION;<br />  }else{<br />#endif<br />    for(; size &gt; 0; offset += 2, --size, ++buffer){<br />      rtc2_write(offset, *(uint8_t*)buffer);<br />    }<br />#if RTC2_BURST<br />  }<br />#endif<br />}<br /><br />void rtc2_mem_read(uint8_t offset, size_t size, void *buffer){<br />  offset += RTC2_MEM_START;<br /><br />  if(RTC2_MEM_READ_INVALID(offset) || RTC2_MEM_READ_INVALID(offset + size * 2))<br />    return;<br /> <br />#if RTC2_BURST<br />  if(size &gt; 1 &amp;&amp; offset == RTC2_MEM_START){<br />    RTC2_START_TRANSMISSION(RTC2_BURST_MEM_READ);<br /><br />    for(; size &gt; 0; offset += 2, --size, ++buffer)<br />      *(uint8_t*)buffer = rtc2_read_byte();<br /><br />    RTC2_STOP_TRANSMISSION;<br />  }else{<br />#endif<br />    for(; size &gt; 0; offset += 2, --size, ++buffer)<br />      *(uint8_t*)buffer = rtc2_read(offset);<br />#if RTC2_BURST<br />  }<br />#endif<br />}<br /><br />// RAM string functions {{{<br />#if RTC2_RAM_STRINGS<br /><br />void rtc2_mem_puts(uint8_t offset, const char *str){<br />  rtc2_mem_write(offset, strlen(str) + 1, str);<br />}<br /><br />void rtc2_mem_gets(uint8_t offset, size_t maxlen, char *str){<br />  offset += RTC2_MEM_START;<br /><br />  if(RTC2_MEM_READ_INVALID(offset))<br />    return;<br /><br />  // here we read until 0 byte or up to maxlen - 1<br />  // to guarantee we always have a valid C string.<br />  for(; maxlen &gt; 1; --maxlen, ++str, offset += 2){<br />    *str = rtc2_read(offset);<br /><br />    if(*str == 0)<br />      return;<br />  }<br /><br />  *str = 0;<br />}<br /><br />#endif<br />// }}}<br /><br />#endif<br />// }}}<br /><br />// Utility functions {{{<br />#if RTC2_UTILITY<br /><br />void rtc2_set_charger(uint8_t flags){<br />  rtc2_write(RTC2_CHARGER_WRITE, flags);<br />}<br /><br />uint8_t rtc2_get_charger(void){<br />  return rtc2_read(RTC2_CHARGER_READ);<br />}<br /><br />uint8_t rtc2_halt(void){<br />  return rtc2_read(RTC2_SECONDS_READ) &gt;&gt; 7;<br />}<br /><br />void rtc2_set_halt(uint8_t v){<br />  rtc2_write(RTC2_SECONDS_WRITE, v &lt;&lt; 7);<br />}<br /><br />uint8_t rtc2_protection(void){<br />  return rtc2_read(RTC2_WP_READ) &gt;&gt; 7;<br />}<br /><br />void rtc2_set_protection(uint8_t v){<br />  rtc2_write(RTC2_WP_WRITE, v &lt;&lt; 7);<br />}<br /><br />#endif<br />// }}}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2449">grzeszal</a> — 9 lis 2014, o 18:23</p><hr />
]]></content>
</entry>
</feed>