<?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=4&amp;t=6441&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-03-21T21:55:24+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=6441&amp;mode</id>
<entry>
<author><name><![CDATA[krawacik3]]></name></author>
<updated>2014-03-21T21:55:24+01:00</updated>
<published>2014-03-21T21:55:24+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=6441&amp;p=75250#p75250</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=6441&amp;p=75250#p75250"/>
<title type="html"><![CDATA[Układ RTCC MCP7940N i ATMega16 jako TWI Master]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=6441&amp;p=75250#p75250"><![CDATA[
Witam.<br />Kupiłem (z mojego chorego nawyku oszczędzania) zegarek <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/25010A.pdf"  class="postlink">MCP7940N</a> i postanowiłem podłączyć go do ATMegi16. Podłączenie jest dobre (schemat wg ds.). Kompletnie nie wiem jak odczytać i zapisać czas do zegara.<br />Kod jest następujący:<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &quot;HD44780.h&quot;<br />#include &quot;I2C_master.h&quot;<br /><br /><br />void LCD_WriteData(unsigned char);<br />void LCD_Initalize(void);<br />void LCD_WriteText(char *);<br />void LCD_GoTo(unsigned char, unsigned char);<br />void LCD_Clear(void);<br />void LCD_Home(void);<br /><br />void LCD_WriteInt(int liczba);<br /><br />void I2C_init(void);<br />uint8_t I2C_start(uint8_t address);<br />uint8_t I2C_write(uint8_t data);<br />uint8_t I2C_read_ack(void);<br />uint8_t I2C_read_nack(void);<br />void I2C_stop(void);<br /><br /><br /><br />int main (void)<br />{<br />/*TWI*/<br />I2C_init();<br /><br />/*TWI*/<br /><br />_delay_ms(100);<br />LCD_Initalize();<br />LCD_WriteInt(51);<br />_delay_ms(300);<br />LCD_Clear();<br />int debb &#91;5&#93;;<br /><br /><br />while(1)<br />{<br />debb&#91;0&#93; = I2C_start(I2C_WRITE);<br /><br />debb&#91;1&#93; = I2C_write(0x00);<br />debb&#91;2&#93; = I2C_start(I2C_READ);<br /><br />debb&#91;4&#93; = I2C_read_ack();<br />I2C_stop();<br />LCD_Clear();<br />LCD_WriteInt(debb&#91;0&#93;);<br />LCD_WriteText(&quot;|&quot;);<br />LCD_WriteInt(debb&#91;1&#93;);<br />LCD_WriteText(&quot;|&quot;);<br />LCD_WriteInt(debb&#91;2&#93;);<br />LCD_WriteText(&quot;|&quot;);<br />//LCD_WriteInt(debb&#91;3&#93;);<br />LCD_WriteInt(debb&#91;4&#93;);<br />_delay_ms(1000);<br />}<br /><br />}<br /><br /><br /><br />void LCD_WriteInt(int liczba)<br />{<br />int wynik_j;<br />int modulo_j;<br />int wynik_d;<br />int modulo_d;<br />int wynik_t;<br />int modulo_t;<br />char wynik;<br />modulo_j = liczba % 10;<br />modulo_d = ((liczba - modulo_j) / 10) % 10;<br />modulo_t = (liczba - (modulo_d*10) - modulo_j) / 100;<br />wynik_j = modulo_j + 48;<br />wynik_d = modulo_d + 48;<br />wynik_t = modulo_t + 48;<br /><br />wynik = wynik_t;<br />LCD_WriteData(wynik);<br /><br />wynik = wynik_d;<br />LCD_WriteData(wynik);<br /><br />wynik = wynik_j;<br />LCD_WriteData(wynik);<br />}[/syntax]<br />Teraz trochę wyjaśnienia: funkcja LCD_WriteInt() działa dobrze, nie trzeba nic w niej zmieniać, a I2C_start, -write i -read_ack są &quot;zapożyczone z Internetu&quot;:<br />[syntax=c]#ifndef  F_CPU<br />#define F_CPU 16000000UL<br />#endif<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;util/twi.h&gt;<br /><br />#include &quot;I2C_master.h&quot;<br /><br />#define F_SCL 100000UL // SCL frequency<br />#define Prescaler 1<br />#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)<br /><br />void I2C_init(void){<br />TWBR = TWBR_val;<br />}<br /><br />uint8_t I2C_start(uint8_t address){<br />// reset TWI control register<br />TWCR = 0;<br />// transmit START condition <br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWSTA) | (1&lt;&lt;TWEN);<br />// wait for end of transmission<br />while( !(TWCR &amp; (1&lt;&lt;TWINT)) );<br /><br />// check if the start condition was successfully transmitted<br />if((TWSR &amp; 0xF8) != TW_START){ return 1; }<br /><br />// load slave address into data register<br />TWDR = address;<br />// start transmission of address<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br />// wait for end of transmission<br />while( !(TWCR &amp; (1&lt;&lt;TWINT)) );<br /><br />// check if the device has acknowledged the READ / WRITE mode<br />uint8_t twst = TW_STATUS &amp; 0xF8;<br />if ( (twst != TW_MT_SLA_ACK) &amp;&amp; (twst != TW_MR_SLA_ACK) ) return 1;<br /><br />return 0;<br />}<br /><br />uint8_t I2C_write(uint8_t data){<br />// load data into data register<br />TWDR = data;<br />// start transmission of data<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br />// wait for end of transmission<br />while( !(TWCR &amp; (1&lt;&lt;TWINT)) );<br /><br />if( (TWSR &amp; 0xF8) != TW_MT_DATA_ACK ){ return 1; }<br /><br />return 0;<br />}<br /><br />uint8_t I2C_read_ack(void){<br /><br />// start TWI module and acknowledge data after reception<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWEA); <br />// wait for end of transmission<br />while( !(TWCR &amp; (1&lt;&lt;TWINT)) );<br />// return received data from TWDR<br />return TWDR;<br />}<br /><br />uint8_t I2C_read_nack(void){<br /><br />// start receiving without acknowledging reception<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br />// wait for end of transmission<br />while( !(TWCR &amp; (1&lt;&lt;TWINT)) );<br />// return received data from TWDR<br />return TWDR;<br />}<br /><br />void I2C_stop(void){<br />// transmit STOP condition<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWSTO);<br />}[/syntax]<br />Do RTCC docierają dane, ponieważ funkcje zwracają 0, gdy odłączę układ zwracają 1. Na wyświetlaczu wyświetlają mi się cztery zera, zamiast trzech zer i sekund. Adres odczytu układu MCP to 11011111 a wysyłania to 11011110.<br />Może ktoś pomoże jak to zrobić? W sumie to pierwszy raz mam styczność z TWI i po przeczytaniu Datasheetu ATMegi i RTCC nie jestem już pewien jak ma wyglądać schemat transmisji czasu do ATMegi. Ja rozumiem to tak:<br />1. Wysłanie START.<br />2. Wysłanie adresu RTCC tak, aby mógł odebrać dane.<br />3. Wysłanie numeru komórki pamięci.<br />4. Wysłanie adresu RTCC tak, aby mógł wysyłać dane.<br />5. Odebranie danych. (ale chyba nie z użyciem ack <img src="https://forum.atnel.pl/images/smilies/icon_rolleyes.gif" alt=":roll:" title="Udaje, że to nie on" /> )<br />6. Wysłanie STOP.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2860">krawacik3</a> — 21 mar 2014, o 21:55</p><hr />
]]></content>
</entry>
</feed>