<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Remote1</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Remote1"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Remote1"/>
	<updated>2026-04-18T09:28:33Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Layout.zip&amp;diff=66334</id>
		<title>Datei:Layout.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Layout.zip&amp;diff=66334"/>
		<updated>2012-05-15T19:22:35Z</updated>

		<summary type="html">&lt;p&gt;Remote1: Eagle Layout&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Eagle Layout&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Receiver-Mainboard_Plattform_Philips_PNX8950&amp;diff=56325</id>
		<title>Receiver-Mainboard Plattform Philips PNX8950</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Receiver-Mainboard_Plattform_Philips_PNX8950&amp;diff=56325"/>
		<updated>2011-04-05T05:52:42Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Wichtige Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Wichtige Links =&lt;br /&gt;
Hier nur die wichtigsten Links (Hauptdiskussionsthread und andere Wikis), den Rest unter &amp;quot;weitergehende Infos im Netz&amp;quot;&lt;br /&gt;
* Diskussionsthread [http://www.mikrocontroller.net/topic/210759 Pollin - Receiver-Mainboard mit Twin DVB-T/C Tuner, NXP PNX8950EH]&lt;br /&gt;
&lt;br /&gt;
* Bedienungsanleitung [http://www1.medion.de/downloads/download.pl?lang=de&amp;amp;filename=bda_md29052_de.pdf&amp;amp;id=7946&amp;amp;type=anleitungen MEDION LIFE S27200 - MD 29052]&lt;br /&gt;
&lt;br /&gt;
= Wichtiger Hinweis =&lt;br /&gt;
&amp;lt;span style=&amp;quot;background-color:red;color:white;font-weight:bold&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vor dem Arbeiten an der Platine oder Öffnen des Gehäuses ist der Netzstecker (230V) zu ziehen. Denn: Der Kühlkörper (des Netzteils) führt eine Spannung von 115V!!!&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Betriebssysteme =&lt;br /&gt;
&lt;br /&gt;
== Bestehenden Inhalt aus dem Flash auslesen ==&lt;br /&gt;
&lt;br /&gt;
Von Benutzer AgentData wird freundlicherweise die [http://www.mikrocontroller.net/attachment/106071/complete_nand_layout.rar gesamte Firmware mit Erklärung sowie der Source für den Dumper] zur Verfügung gestellt. Der für den direkten Zugriff auf das NAND benötigte Code befand sich in der Datei $F/Windows/TmToolbox.dll (read/write/erase).&lt;br /&gt;
&lt;br /&gt;
Damit dürfte der Grundstein für jegliche Weiterentwicklung gelegt sein.&lt;br /&gt;
&lt;br /&gt;
== Neues Firmwareimage aufspielen ==&lt;br /&gt;
&lt;br /&gt;
# Auf einen mit FAT32 formatierten USB-Stick folgende Datein kopieren: flashing.txt, phStbRootApp_256M_0_t.mi, phStbRootApp_256M_1_t.mi sowie WinCe1.nb0. Diese befinden sich beispielsweise im Ordner WCE1 der Datei swu.zip&lt;br /&gt;
# Receiver hinten am Netzteil ausschalten&lt;br /&gt;
# SW1 auf ON (DIL Schalter auf Pollin Board)&lt;br /&gt;
# USB-Stick am Rückwärtigen USB-Port des Receivers anschließen&lt;br /&gt;
# Receiver hinten am Netzteil einschalten&lt;br /&gt;
# Am Receiver vorne auf Power drücken. Bei Fehlermeldung auf Bildschirm: Anderen USB Stick (oder per SD-Karte + Reader) probieren und/oder Receiver per Fernbedienung einschalten. Wenn alles funktioniert, erscheint eine Anzeige auf dem Bildschirm, daß das Update durchgeführt wird und man den Receiver nicht ausschalten soll, bis das Update eingespielt ist. Falls irgend etwas falsch läuft, startet das Windows CE und zeigt den Telegen-Desktop. Dann nochmal alles überprüfen.&lt;br /&gt;
# Auf dem roten, 4-stelligen Frontdisplay der Box wird nun für die insgesamt 4 Flash-Vorgänge jeweils der Fortschritt in Prozent angezeigt. Achtung: Es werden insgesamt 4 Dateien einzeln geflasht, die Prozentzahl klettert also vier Mal bis auf die 100%.&lt;br /&gt;
# Nach kurzer Zeit (1 oder 2 Minuten) erscheint eine Meldung, dass das Software Update erfolgreich war&lt;br /&gt;
# Receiver am Netzteil ausschalten.&lt;br /&gt;
# SW1 auf OFF setzen. &lt;br /&gt;
&lt;br /&gt;
Nun wird die Box beim Einschalten auf dem TV einen hin- und herwandernden roten Balken zeigen. Die weiteren Programmpunkte sind selbsterklärend.&lt;br /&gt;
&lt;br /&gt;
== WindowsCE ==&lt;br /&gt;
&lt;br /&gt;
*Windows CE 5.0&lt;br /&gt;
*Windows CE Kernel for MIPS (Built on Mar 29 2005 at 14:00:54)&lt;br /&gt;
*Telegent Kernel V0.9.3.16 (Built on Sep  4 2006 at 22:23:55)&lt;br /&gt;
&lt;br /&gt;
User AgentData hat das [http://www.mikrocontroller.net/attachment/106025/org_firmware_dump.zip im Auslieferungszustand auf dem Gerät befindliche WindowsCE] ausgelesen (siehe hierzu [http://www.mikrocontroller.net/articles/Receiver-Mainboard_Plattform_Philips_PNX8950#Bestehenden_Inhalt_aus_dem_Flash_auslesen Inhalt aus dem Flash auslesen]). Dadurch kann beispielsweise eine [http://www.mikrocontroller.net/articles/Receiver-Mainboard_Plattform_Philips_PNX8950#MoreTv_als_Medion_gelabelt mit MoreTV &amp;quot;aktualisierte&amp;quot;] Box nun auch wieder in den Auslieferungszustand zurückversetzt werden. Die [http://www.mikrocontroller.net/articles/Receiver-Mainboard_Plattform_Philips_PNX8950#Neues_Firmwareimage_aufspielen Update-Prozedur] ist identisch.&lt;br /&gt;
&lt;br /&gt;
== MoreTv als Medion gelabelt ==&lt;br /&gt;
&lt;br /&gt;
Benötigt wird:&lt;br /&gt;
# SATA-HD mit 160GB oder mehr (im Original 250GB)&lt;br /&gt;
# USB-Stick (FAT32)&lt;br /&gt;
# [https://www.more.tv/softwareupdate/SWU_Finland/SWU_Finland_V1.0.3.454/swu.zip SoftWareUpdate (SWU_Finland_V1.0.3.454)]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ein großes Danke gilt den Usern Fritz und M. W.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier die Kurzanleitung zum &#039;Tuning&#039;:&lt;br /&gt;
* Erster Start der Box&lt;br /&gt;
:WindowsCE meldet sich und kann mittels USB-Maus und Tastatur bedient werden. Nach erfolgtem Flash-Vorgang ist dies nicht mehr möglich.&lt;br /&gt;
&lt;br /&gt;
* Den Inhalt des Ordner WCE1, aus der Datei [https://www.more.tv/softwareupdate/SWU_Finland/SWU_Finland_V1.0.3.454/swu.zip swu.zip] (SWU_Finland_V1.0.3.454), auf einen formatierten USB-Stick (FAT32) kopieren und [http://www.mikrocontroller.net/articles/Receiver-Mainboard_Plattform_Philips_PNX8950#Neues_Firmwareimage_aufspielen wie beschrieben] aufspielen&lt;br /&gt;
&lt;br /&gt;
* SATA-HD vorbereiten&lt;br /&gt;
:# Auf der einzubauenden SATA-HD zuvor eine Extended Partition mit zwei logischen Laufwerken anlegen. (FAT32, Typ &#039;b&#039; bei fdisk unter Linux). Mit dem kostenlosen Windows Programm &amp;quot;[http://www.easeus.com/download.htm EASEUS Partition Master 8.0.1 Home Edition]&amp;quot; lässt sich dies ebenfalls einfach erreichen.&lt;br /&gt;
:# Auf das ersten logischen Laufwerk (minimum 2GB, im Original 19,53GB, das entspricht exakt 20000MB) den gesamten Inhalt des zuvor ausgepackten [https://www.more.tv/softwareupdate/SWU_Finland/SWU_Finland_V1.0.3.454/swu.zip SoftWareUpdates] kopieren.&lt;br /&gt;
:# Die Ordner moreTVn und moreTVn.INIT zu moreTV und moreTV.INIT umbenenen.&lt;br /&gt;
:# Das zweite Laufwerk (je größer desto besser, im Original 213,4GB) bleibt leer.&lt;br /&gt;
&lt;br /&gt;
: Die fehlenden Ordner auf der Festplatte werden beim ersten Starten der Box automatisch angelegt.&lt;br /&gt;
: ACHTUNG: Die USB-Anschlüsse werden nach dem Aufspielen der MoreTV Firmware nicht mehr unterstützt. Eine Ausnahme bildet einzig und alleine das [http://www.mikrocontroller.net/articles/Receiver-Mainboard_Plattform_Philips_PNX8950#Neues_Firmwareimage_aufspielen Flash-Update].&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
&lt;br /&gt;
:Die CPU wird pauschal von Linux unterstützt.&lt;br /&gt;
&lt;br /&gt;
== Interessant zum weiteren Testen ==&lt;br /&gt;
&lt;br /&gt;
*elecard firmware&lt;br /&gt;
*MontaVista Linux Professional Edition&lt;br /&gt;
&lt;br /&gt;
= Unterstützte Codecs =&lt;br /&gt;
&lt;br /&gt;
Quelle: [http://www.synnex.com.tw/oem/mic_link/seminar%20download/y70303.pdf]&lt;br /&gt;
&lt;br /&gt;
*dual: SD MPEG-1/2&lt;br /&gt;
*single: SD MPEG-4, WM9, H264,DivX; HD MPEG-2 (1080i), WM9(720p)&lt;br /&gt;
*Audio: dual stereo (2.0 + 2.0),MPEG-1, Dolby AC-3&lt;br /&gt;
&lt;br /&gt;
= Bezugsquellen = &lt;br /&gt;
&lt;br /&gt;
===Platinen===&lt;br /&gt;
* [http://www.pollin.de/shop/dt/NzQ5OTA2OTk-/Bausaetze_Module/Module/Receiver_Mainboard_mit_Twin_DVB_T_Tuner.html Pollin : Receiver-Mainboard mit Twin DVB-T Tuner (390 052, 7,95€)]&lt;br /&gt;
* [http://www.pollin.de/shop/dt/NjQ5OTA2OTk-/Bausaetze_Module/Module/Receiver_Mainboard_mit_Twin_DVB_C_Tuner.html Pollin : Receiver-Mainboard mit Twin DVB-C Tuner (390 053, 7,95€)]&lt;br /&gt;
* [http://www.pollin.de/shop/dt/MzQxODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/RS232_Einbaubuchse.html Pollin : RS232-Einbaubuchse (721 856, 0,25€)], zur Befestigung werden noch zwei passende Sechskant-Schraubbolzen benötigt&lt;br /&gt;
* [http://www.pollin.de/shop/dt/NDQxODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/USB_2_0_Einbaubuchse.html Pollin : USB 2.0-Einbaubuchse (721 855, 0,25€)]&lt;br /&gt;
&lt;br /&gt;
===Zubehör===&lt;br /&gt;
:Netzteil, Gehäuse, Fernbedienung:&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NjUwOTQ2OTk-/Stromversorgung/Netzgeraete/Festspannungs_Netzgeraete/Schaltnetzteil_DELTA_EADP_50DF_12_V_4_16_A.html Pollin : Schaltnetzteil DELTA EADP-50DF, 12 V-/4,16 A (350 943 , 4,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MDg4OTM1OTk-/Bauelemente_Bauteile/Gehaeuse/Stahlblech_Gehaeuse_mit_Frontblende.html Pollin : Stahlblech-Gehäuse mit Frontblende (460 119, 2,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/Nzc5OTczOTk-/SAT_Antennentechnik/Satelliten_Technik/Fernbedienungen/Infrarot_Fernbedienung_RCX155.html Pollin : Infrarot-Fernbedienung RCX155 (620 022, 1,95€)]&lt;br /&gt;
:SATA:&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NTQxODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/SATA_Kabel.html Pollin : SATA-Kabel, 2x SATA-Stecker, 0,35m (721 854, 0,50€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MDM0OTcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/HDD_Stromversorgungskabel.html Pollin : PC-Stromversorgungskabel, 2x 5,25&amp;quot;- Stecker, 2x HDD-Stecker, 70mm (720 569, 0,20€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NDI1ODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/SATA_Stromversorgungsadapter.html Pollin : SATA-Stromversorgungsadapter (721 475, 0,85)] oder alternativ&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MTUwOTcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/SATA_Stromversorgungsadapter.html Pollin : SATA-Stromversorgungsadapter, mit Rastnase! (720 948, 0,55)]&lt;br /&gt;
:WLAN:&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NDY5ODgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/WLAN_miniPCI_Karte_XG_603.html Pollin : WLAN miniPCI-Karte XG-603 (711 035, 3,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MjUwOTgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/Wireless_LAN_Antennen_Adapterkabel.html Pollin : WLAN-Antennen-Adapterkabel (710 947, 4,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MTM5ODgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/Wireless_LAN_Rundstrahlantenne.html Pollin : WLAN-Antenne 4 dBi. Länge 140 mm Reverse-SMA (710 068, 1,95€)] oder alternativ &lt;br /&gt;
*[http://www.pollin.de/shop/dt/NzY3ODgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/WLAN_Antenne_FSC_5_dBi_RP_SMA.html Pollin : WLAN-Antenne, mit Standfuß, Reverse-SMA, 5 dBi (711 232, 3,95€)] oder alternativ&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NDE0OTgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/Wireless_LAN_Rundstrahlantenne.html Pollin : WLAN-Antenne, Reverse-SMA, 5 dBi (710 585, 6,95€)] oder alternativ&lt;br /&gt;
*[http://www.pollin.de/shop/dt/ODI5ODgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/Wireless_LAN_Antenne.html Pollin : WLAN-Antenne, mit magnetischem Standfuß, Reverse-SMA, 7 dBi (711 071, 6,95€)] oder alternativ&lt;br /&gt;
*[http://www.reichelt.de/?ACTION=3;ARTICLE=61136;PROVID=2402 Reichelt: LAN DN-70100, WLAN-Antenne, Reverse-SMA, 5 dBi (LAN DN-70100, 3,65€)]&lt;br /&gt;
 &lt;br /&gt;
:DVB-T und DVB-C:&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MzQ3ODI0OTk-/SAT_Antennentechnik/Kabel/Antennen_Anschlusskabel_75_150_mm.html Pollin : Antennen-Anschlusskabel 75 Ω, 150 mm (571 256, 0,15€)] zum Durchschleifen des DVB-Signals&lt;br /&gt;
:DVB-T:&lt;br /&gt;
*Bitte beachten: Passive antennen sind grundsätzlich nicht zu empfehlen. Zumindest nicht im Zimmer. Ausser man wohnt am Sender :D&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MTc4ODI0OTk-/SAT_Antennentechnik/DVB_T_DVB_C/Antennen/DVB_T_Antenne_QOSMIO.html Pollin : DVB-T Antenne QOSMIO, passiv (571 128, 2,95€)]&lt;br /&gt;
:DVB-S:&lt;br /&gt;
*[http://www.elsner-computer.de/product_info.php?info=p430032_Dream-Multimedia-Tuner-7020S---7020Si---DVB-S.html Tuner 7020S Elsner Shop 39€. ]&lt;br /&gt;
*[http://www.hm-sat-shop.de/receiver-digital-dreambox/sat-tuner-fuer-dreambox-7020-philips.html HM Sat Shop:DVB-S Tuner zum Sat-Umbau, 49€.] &lt;br /&gt;
*[http://www.devilcards.de/Ersatzteile-Dreambox/Dream-Multimedia-Tuner-7020S-7020Si-DVB-S::225.html DevilCards Dream Multimedia Tuner 7020S DVB-S 37€ ]&lt;br /&gt;
Entweder zwei bestücken oder exklusiv einen. Mischbetrieb scheinbar nicht möglich!&lt;br /&gt;
&lt;br /&gt;
*...außerdem Plexiglas/Kunststoff-Zuschnitt (13cm x 15cm) als HD-Träger sowie diverse Schrauben aus der PC-Grabbelkiste (7* Gehäuse, 1* Front-USB, 4* Schaltnetzteil, 6* Mainboard, 4* HD-Träger, 4* HD, 3* Frontpanel)&lt;br /&gt;
&lt;br /&gt;
= Hardware =&lt;br /&gt;
== technische Daten ==&lt;br /&gt;
* Betriebsspannung 12 V-&lt;br /&gt;
* Stromaufnahme ohne HDD max. 2 A&lt;br /&gt;
* 2x Philips DVB-T Tuner TU1216L/IVP&lt;br /&gt;
* HDD-Stromversorgung on Board&lt;br /&gt;
* Anschlüsse extern: 2x Tuner In, 2x Tuner Out, LAN 10/100 Mbps, USB 2.0, optischer Audioausgang, AV-Out (Cinch), S-Video, 2x Scart&lt;br /&gt;
* interne Ports/Anschlüsse: 3x USB 2.0, 2x SATA, RS232, miniPCI für WLAN-Karte (XG-603), Smartcard-Reader, CI-Slot&lt;br /&gt;
&lt;br /&gt;
== Jumper ==&lt;br /&gt;
* J1: (Header 2x5, nicht bestückt)&lt;br /&gt;
* J2: RS-232 Console (3:RX=RS232.3, 5:TX=RS232.2, 9:GND=RS232.5, Header 2x5)&lt;br /&gt;
* J4: (Header 2*10)&lt;br /&gt;
* J6: (Header 2x1, neben HD-Power)&lt;br /&gt;
* J8: (Header 2x3 nicht bestückt)&lt;br /&gt;
* J27: Massepunkt(1:GND, 2:GND, Header 2*1, zwischen SCART und Audio-Buchse)&lt;br /&gt;
* J30: USB Port 4 (über 4 pol Kabel verbunden mit Front USB, Header 1x4) &lt;br /&gt;
* J31: USB Port 3 (Header 1x4)&lt;br /&gt;
* J32: (Header 2x1, nicht bestückt, neben SW1)&lt;br /&gt;
* J34: an PIN 32 DVB-T-Tuner (Header 2x1, neben Tuner 1, bei DVB-C-Tuner nicht benutzt)&lt;br /&gt;
* J35: (Header 2x1, nicht bestückt, neben Tuner 1)&lt;br /&gt;
* J36: an PIN 32 DVB-T-Tuner (Header 2x1, neben Tuner 2, bei DVB-C-Tuner nicht benutzt)&lt;br /&gt;
* J37: (Header 2x1, nicht bestückt, neben Tuner 2)&lt;br /&gt;
* J41: Anschluß Bedien-PCB, Infrarot-Receiver (5 pol)&lt;br /&gt;
* J42: Anschluß Bedien-PCB, Tastatur + Display (10 pol)&lt;br /&gt;
* J43: 12V von Schaltnetzteil&lt;br /&gt;
* J45: nicht bestückt, Hohlbuchse, 12V Spannungsversorgung&lt;br /&gt;
* J46: USB Port 2 (Header 1x4)&lt;br /&gt;
* J47: SPDIF-Ausgang&lt;br /&gt;
&lt;br /&gt;
== LEDs ==&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:lightgreen;color:black&amp;quot;&amp;gt;LED1: grün&amp;lt;/span&amp;gt;, blinkt, wenn am rückwärtigen USB-Anschluss beispielsweise eine Maus angeschlossen ist (zwischen U1 und nicht bestücktem HDMI-Chip U42)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:blue;color:white&amp;quot;&amp;gt;LED2: blau&amp;lt;/span&amp;gt; (neben Befestigungsloch H3)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:red;color:white&amp;quot;&amp;gt;LED3: rot&amp;lt;/span&amp;gt;, wahrscheinlich Netzkontroll-LED(Nähe J4)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:lightgreen;color:black&amp;quot;&amp;gt;LED4: grün&amp;lt;/span&amp;gt;, leuchtet nur ganz schwach (neben LED3, Nähe J4)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:lightgreen;color:black&amp;quot;&amp;gt;LED5: grün&amp;lt;/span&amp;gt; (neben Prozessor)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:blue;color:white&amp;quot;&amp;gt;LED6: blau&amp;lt;/span&amp;gt; (neben Prozessor)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:red;color:white&amp;quot;&amp;gt;LED7: rot&amp;lt;/span&amp;gt; (neben LED5)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;background-color:lightgreen;color:black&amp;quot;&amp;gt;LED8: grün&amp;lt;/span&amp;gt;, zeigt HD-Schreibzugriff bei einer Aufnahme an (neben J6, USB Port 2)&lt;br /&gt;
&lt;br /&gt;
==Varianten==&lt;br /&gt;
===DVB-T===&lt;br /&gt;
===DVB-C===&lt;br /&gt;
Die Box kann mit großer Sicherheit keine QAM256 modulierten Programme wiedergeben.&lt;br /&gt;
Programme, die QAM64 moduliert sind werden problemlos und sicher wiedergegeben&lt;br /&gt;
&lt;br /&gt;
== Bilder/Innenleben ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;300&amp;quot; heights=&amp;quot;225&amp;quot; perrow=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
Bild:moretv_1.jpg|Gesamtansicht&lt;br /&gt;
Bild:moretv_2.jpg|JTAG-Anschluss für LPC921F (unter anderem) und Platz zur Montage einer 3,5&amp;quot; Festplatte&lt;br /&gt;
Bild:moretv_3.jpg|Board komplett&lt;br /&gt;
Bild:moretv_4.jpg|DVI – nicht bestückt&lt;br /&gt;
Bild:moretv_5.jpg|DVB-T Tuner&lt;br /&gt;
Bild:moretv_6.jpg|CPU RAM etc.&lt;br /&gt;
Bild:moretv_7.jpg|mini PCI, Sata, CI-Slot, Smartcard&lt;br /&gt;
Bild:moretv_8.jpg|Rückseite komplett&lt;br /&gt;
Bild:moretv_9.jpg|CI-Controller&lt;br /&gt;
Bild:moretv_10.jpg|Sata-Controller&lt;br /&gt;
Bild:moretv_11.jpg|RAM und TDA8024T SmartCard-Interface&lt;br /&gt;
Bild:moretv_12.jpg|LAN DP83816 (fast identisch zu SiS 900)&lt;br /&gt;
Bild:moretv_13.jpg|SW1 auf ON = SW-Update&amp;lt;br/&amp;gt;SW2 auf ON = JTAG Enable&lt;br /&gt;
Bild:moretv_14.jpg|Stromversorgung&lt;br /&gt;
Bild:moretv_15.jpg|Anschluss J4&lt;br /&gt;
Bild:EJTAG.jpg|CON1: EJTAG für den PNX8950&lt;br /&gt;
Bild:Tuner_Jumper1.JPG|Wie man sieht, müssen keinerlei Jumper gesetzt sein, um DVB-T empfangen zu können.&lt;br /&gt;
Bild:Console.png|RS-232 Console auf J2&lt;br /&gt;
Bild:lpc_8051_power.png|3,3Volt auf J4&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Schnittstellen ==&lt;br /&gt;
&lt;br /&gt;
* 4x USB &lt;br /&gt;
** 3x intern: J31 USB Port3, J46 USB Port2&lt;br /&gt;
** 2x extern: J30 USB Port4 (Frontpanel), CON9&lt;br /&gt;
** Pinout: PIN4:GND/Schwarz, PIN3:D+/Grün, PIN2:D-/Weiss, Pin1:+5V/Rot&lt;br /&gt;
&lt;br /&gt;
* 2x RS-232&lt;br /&gt;
:* 1x intern, Pinbelegung (J2)&lt;br /&gt;
::* &#039;&#039;&#039;hier einfügen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:*1x extern, Pinbelegung (J33):&lt;br /&gt;
::* 6 gnd&lt;br /&gt;
::* 5 rx1 r2in MAX2333 (U10)&lt;br /&gt;
::* 4 rx2 r1in MAX2333 (U10)&lt;br /&gt;
::* 3 tx1 T2out MAX2333 (U10)&lt;br /&gt;
::* 2 tx2 T1out MAX2333 (U10)&lt;br /&gt;
::* 1 gnd  0&lt;br /&gt;
::* das O ist die Markierung auf der Platine&lt;br /&gt;
&lt;br /&gt;
== Chips ==&lt;br /&gt;
Übersicht über die verwendeten Bausteine mit Links auf ensprechende Datenblätter, Quellen etc.&lt;br /&gt;
&lt;br /&gt;
* Multimedia-CPU Philips PNX8950EH/M2/S1&lt;br /&gt;
**[http://datasheet.octopart.com/PNX8950EH/M2/S1%2C55-NXP-datasheet-8325175.pdf Datasheet PNX8950EH/M2/S1]&lt;br /&gt;
**[http://www.brightsign.biz/documents/HD2000HardwareGuide.pdf Brightsign Hardwareguide]&lt;br /&gt;
**[http://www.kanecomputing.co.uk/pdfs/mds_mds810.pdf MDS-810]&lt;br /&gt;
*[http://www.alldatasheet.com/datasheet-pdf/pdf/98585/SAMSUNG/K4H511638C-UCCC.html 4x 512 MBit DDR SDRAM SAMSUNG K4H511638C-UCCC]&lt;br /&gt;
* [http://www.hynix.com/datasheet/pdf/flash/HY27(U_S)S(08_16)121A%20Series(Rev1.3).pdf HYNIX HY27US08121A 512 Mbit NAND Flash]&lt;br /&gt;
* [http://www.siliconimage.com/docs/SiI-DS-0102-D.pdf SiI3512 SATA150 Controller]&lt;br /&gt;
*[http://www.national.com/ds/DP/DP83816.pdf 10/100 Mbps PCI Ethernet-Controller NATIONAL DP83816]&lt;br /&gt;
* High Speed USB PCI Host Controller Philips ISP1561BM [http://www.nxp.com/acrobat_download2/expired_datasheets/ISP1561_2.pdf Datasheet]&lt;br /&gt;
* [http://www.maxim-ic.com/datasheet/index.mvp/id/1068 MAX3222]&lt;br /&gt;
* PNX8510HW [http://www.datasheetcatalog.org/datasheet/philips/PNX8510_PNX8511_4.pdf Datasheet]&lt;br /&gt;
* Bedienteil mit LED-Display, Infrarotempfänger usw.&lt;br /&gt;
* In der DVB-C-Version: Philips CU1216 DVB-C Tuner [http://read.pudn.com/downloads138/sourcecode/others/589797/CU1216L-3-datasheet.pdf Datasheet]&lt;br /&gt;
** Philips TDA10023 (DVB-C Channel Decoder) [http://www.datasheetdownload.com/download.php?id=677273 Datasheet]&lt;br /&gt;
* In der DVB-T-Version: Philips TU1216 DVB-T Tuner&lt;br /&gt;
** Philips TDA10046 (DVB-T Channel Decoder) [http://www.nxp.com/acrobat/literature/9397/75009522.pdf Spec Sheet] [http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/dvb/frontends/tda1004x.c - linuxtv.org Frontend Treiber]&lt;br /&gt;
** Philips TDA6650 (5 V mixer/oscillator and low noise PLL synthesizer for hybrid terrestrial tuner) [http://www.nxp.com/documents/data_sheet/TDA6650TT_6651TT.pdf Datasheet] [http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/dvb/frontends/tda665x.c - linuxtv.org Tuner Treiber]&lt;br /&gt;
* Philips TDA8024T (IC Card Interface) [http://www.nxp.com/documents/data_sheet/TDA8024.pdf Datasheet]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nicht bestückte ICs:&lt;br /&gt;
* U42 DVI (wahrscheinlich [http://www.nxp.com/documents/data_sheet/TDA9983B.pdf Philips TDA9983])&lt;br /&gt;
* U40 ????&lt;br /&gt;
* U41 ????&lt;br /&gt;
* U44 ????&lt;br /&gt;
* U45 ????&lt;br /&gt;
* U48 ????&lt;br /&gt;
* U51 ????&lt;br /&gt;
* U59 ????&lt;br /&gt;
&lt;br /&gt;
== Fernbedienung ==&lt;br /&gt;
&lt;br /&gt;
[[IRMP]] Codes:  &lt;br /&gt;
&lt;br /&gt;
Protokoll: NEC&amp;lt;br /&amp;gt;&lt;br /&gt;
Geräte ID: 0x6B44&amp;lt;br /&amp;gt;&lt;br /&gt;
Tastencodes:&amp;lt;br &amp;gt;&lt;br /&gt;
* 00	0&lt;br /&gt;
* 01	EXIT&lt;br /&gt;
* 02	8&lt;br /&gt;
* 03	INFO&lt;br /&gt;
* 04	4&lt;br /&gt;
&lt;br /&gt;
* 06	HELP&lt;br /&gt;
* 07	OK&lt;br /&gt;
* 08	2&lt;br /&gt;
* 09	REC&lt;br /&gt;
 &lt;br /&gt;
* 0B	Marker&lt;br /&gt;
* 0C	6&lt;br /&gt;
&lt;br /&gt;
* 0E	Down&lt;br /&gt;
* 0F	V-&lt;br /&gt;
* 10	1&lt;br /&gt;
* 11	AV&lt;br /&gt;
* 12	9&lt;br /&gt;
* 13	Right&lt;br /&gt;
* 14	5&lt;br /&gt;
* 15	Archiv&lt;br /&gt;
&lt;br /&gt;
* 17	P-&lt;br /&gt;
* 18	3&lt;br /&gt;
* 19	Up&lt;br /&gt;
* 1A	Yellow&lt;br /&gt;
* 1B	Left&lt;br /&gt;
* 1C	7&lt;br /&gt;
* 1D	Stop/LIVE&lt;br /&gt;
* 1E	RED&lt;br /&gt;
&lt;br /&gt;
* 40	MORE&lt;br /&gt;
* 41	LIST&lt;br /&gt;
* 42	FFWD&lt;br /&gt;
&lt;br /&gt;
* 48	TV&lt;br /&gt;
* 49	#&lt;br /&gt;
* 4A	GREEN&lt;br /&gt;
&lt;br /&gt;
* 4C	EPG&lt;br /&gt;
&lt;br /&gt;
* 4E	SLOW&lt;br /&gt;
&lt;br /&gt;
* 50	P+&lt;br /&gt;
* 51	*&lt;br /&gt;
* 52	POWER&lt;br /&gt;
&lt;br /&gt;
* 54	FREW&lt;br /&gt;
&lt;br /&gt;
* 56	PAUSE&lt;br /&gt;
&lt;br /&gt;
* 58	Setup&lt;br /&gt;
* 59	TEXT&lt;br /&gt;
* 5A	BLUE&lt;br /&gt;
&lt;br /&gt;
* 5C	Chap+&lt;br /&gt;
&lt;br /&gt;
* 5E	PiP&lt;br /&gt;
&lt;br /&gt;
Die Tasten Stumm, Chapter+ und Play funktionieren bei meiner FB nicht.&lt;br /&gt;
Die hatte einen Dauerkontakt auf einer dieser Tasten. Darum musste ich eine Leiterbahn durchtrennen.&lt;br /&gt;
&lt;br /&gt;
= Software =&lt;br /&gt;
Übersicht über verwendete Software (Betriebssysteme, Compiler, Tools, etc)&lt;br /&gt;
&lt;br /&gt;
* Software Update: [http://www.mikrocontroller.net/attachment/105209/swu.zip swu.zip]&lt;br /&gt;
&lt;br /&gt;
* Bootloader&lt;br /&gt;
:Eventuell [http://www.denx.de/wiki/U-Boot/SourceCode U-Boot] support mit diesen 4 patches:&lt;br /&gt;
:# [http://lists.denx.de/pipermail/u-boot/attachents/20061204/e9922ec2/attachment.obj pnx8550support.diff.gz]&lt;br /&gt;
:# [http://lists.denx.de/pipermail/u-boot/attachments/20061206/556029b0/attachment.obj nxp_i2c.diff.gz]&lt;br /&gt;
:#  [http://lists.denx.de/pipermail/u-boot/attachments/20061211/bff13619/attachment.obj nxp_pci.diff.gz]&lt;br /&gt;
:# [http://lists.denx.de/pipermail/u-boot/attachments/20061211/8d42666e/attachment.obj mips_timer2.diff]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Overview&lt;br /&gt;
+The Silverbox is a development platform based on the NXP PNX8550&lt;br /&gt;
+(Nexperia) media processor.  It consists of a MIPS32 compatible PR4450&lt;br /&gt;
+core, accompanied by two TriMedia processors.  Typical use for the&lt;br /&gt;
+PNX8550 is in settop box and advanced analogue and digital TV sets.&lt;br /&gt;
+&lt;br /&gt;
+This first version of U-Boot for this platform supports a minimal set&lt;br /&gt;
+of commands and hardware.  Feature to be added in the near future are&lt;br /&gt;
+PCI bus, Ethernet, NAND flash and USB support.&lt;br /&gt;
+&lt;br /&gt;
+Boot Methods&lt;br /&gt;
+U-Boot for the Silverbox is typically loaded into SDRAM using an EJTAG&lt;br /&gt;
+probe.  The load address and entry point is 0xA0010000.&lt;br /&gt;
+&lt;br /&gt;
+As NAND flash support is not yet available a single page NAND flash&lt;br /&gt;
+loader is also not available.  This limits this U-Boot version, but&lt;br /&gt;
+a single page loader based on U-Boot 1.1.3 is available on request.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Screenshot der Windows CE 5.0 Oberfläche (über VNC mit der Box verbunden http://efonvnc.sourceforge.net/)&lt;br /&gt;
&lt;br /&gt;
[[Datei:CEscreenshot.png]]&lt;br /&gt;
&lt;br /&gt;
= Anwendungen und Ideen =&lt;br /&gt;
==Realisierte Projekte/Anwendungen==&lt;br /&gt;
&lt;br /&gt;
=== ftp-Server unterschieben ===&lt;br /&gt;
* Auf der Festplatte in der Datei &amp;quot;moreTV.cfg&amp;quot; im Abschnitt &amp;quot;Shell_startup&amp;quot; die Zeile für den Start des ftp-Servers einfügen&lt;br /&gt;
  &amp;lt;Shell_startup&amp;gt;&lt;br /&gt;
  &amp;lt;run cmd=&amp;quot;$H\ftpsvr.exe&amp;quot;/&amp;gt;  #### diese Zeile einfügen ohne diesen Kommentar!&lt;br /&gt;
  &amp;lt;run cmd=&amp;quot;$H\moreTV\DC.exe&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!--  &amp;lt;run cmd=&amp;quot;$H\moreTV\Ivon.exe&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
  &amp;lt;run cmd=&amp;quot;$H\moreTV\MaxAktiv.exe&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/Shell_startup&amp;gt;&lt;br /&gt;
* Den FTP-Server [http://www.mikrocontroller.net/attachment/104995/ftpsvr.exe hier] downloaden und nach $H kopieren, also die erste Partition der Festplatte.&lt;br /&gt;
* Für&#039;s Login des FTP-Servers irgendwelche Werte eingeben, z.B.&lt;br /&gt;
   Benutzer: root&lt;br /&gt;
   Passwort: root&lt;br /&gt;
* Die Exe-Dateien aus dem Windows-Verzeichnis können aber nicht bzw. nicht alle kopiert werden. Im Totalcommander werden die Attribute 555 angezeigt. Vielleicht hat ja noch jemand eine Idee, wie man das überwinden kann.&lt;br /&gt;
&lt;br /&gt;
==Anwendungsideen==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unter Linux:&#039;&#039;&#039;&lt;br /&gt;
Festplattenreceiver,&lt;br /&gt;
Asterisk Server,&lt;br /&gt;
NAS,&lt;br /&gt;
Car-PC,&lt;br /&gt;
Multimedia Client/Server,&lt;br /&gt;
Wetterstation logging Server,&lt;br /&gt;
Solar logging Server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unter WinCE&#039;&#039;&#039;:&lt;br /&gt;
Festplattenreceiver,&lt;br /&gt;
NAS,&lt;br /&gt;
Car-PC,&lt;br /&gt;
Media Portal Client/Server,&lt;br /&gt;
Kamera Server,&lt;br /&gt;
Spielekonsole für minigames,&lt;br /&gt;
Download Server&lt;br /&gt;
&lt;br /&gt;
= weitergehende Infos im Netz =&lt;br /&gt;
Alles was noch weiterführende Infos bietet. Andere Wikis, Beiträge, etc.&lt;br /&gt;
&lt;br /&gt;
* [http://www.oohito.com/wince/mips_o_j.htm MIPS FTP Server]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Receiver-Mainboard_Plattform_Philips_PNX8950&amp;diff=56072</id>
		<title>Receiver-Mainboard Plattform Philips PNX8950</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Receiver-Mainboard_Plattform_Philips_PNX8950&amp;diff=56072"/>
		<updated>2011-03-28T12:32:30Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Betriebssysteme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Wichtige Links =&lt;br /&gt;
Hier nur die wichtigsten Links (Hauptdiskussionsthread und andere Wikis), den Rest unter &amp;quot;weitergehende Infos im Netz&amp;quot;&lt;br /&gt;
* Disskussionsthread [http://www.mikrocontroller.net/topic/210759 Pollin - Receiver-Mainboard mit Twin DVB-T/C Tuner, NXP PNX8950EH]&lt;br /&gt;
&lt;br /&gt;
= Übersicht Features =&lt;br /&gt;
===Betriebssysteme===&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;Windows CE 5.0&amp;quot;&lt;br /&gt;
**Windows CE Kernel for MIPS Built on Mar 29 2005 at 14:00:54&lt;br /&gt;
**Telegent Kernel V0.9.3.16, Built on Sep  4 2006 at 22:23:55&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;MoreTv! Als Medion gelabelt&amp;quot;&lt;br /&gt;
** How to fläsch&lt;br /&gt;
**1. SW1 auf ON (DIL Schalter auf Pollin Board)&lt;br /&gt;
**2. Inhalt von [http://www.mikrocontroller.net/attachment/105209/swu.zip WCE1] auf USB-Stick (Fat32) kopieren und HINTEN an den Receiver stecken.&lt;br /&gt;
**3. Receiver hinten am Netzteil einschalten&lt;br /&gt;
**4. Am Receiver vorne auf Power drücken. Bei Fehlermeldung auf Bildschirm: Anderen USB Stick probieren und/oder Receiver per Fernbedienung einschalten. Wenn alles funktioniert, erscheint eine Anzeige auf dem Bildschirm, daß das Update durchgeführt wird und man den Receiver nicht ausschalten soll, bis das Update eingespielt ist. Falls irgend etwas falsch läuft, startet das Windows CE und zeigt den Telegen-Desktop. Dann nochmal alles überprüfen.&lt;br /&gt;
**5. Nach kurzer Zeit (1 Minute oder 2) erscheint eine Meldung SW Update succeeded oder so, habe ich schon wieder vergessen.&lt;br /&gt;
**6. Receiver am Netzteil ausschalten.&lt;br /&gt;
**7. SW1 auf OFF setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;Linux&amp;quot;&lt;br /&gt;
:Der uC wird pauschal von Linux unterstützt.&lt;br /&gt;
:Interessante Versionen zum weiteren Testen sind:&lt;br /&gt;
**Dreambox Image&lt;br /&gt;
**elecard firmware&lt;br /&gt;
**MontaVista Linux Professional Edition&lt;br /&gt;
&lt;br /&gt;
===Unterstützte Codecs===&lt;br /&gt;
&lt;br /&gt;
*dual: &lt;br /&gt;
:SD MPEG-1/2&lt;br /&gt;
*single:&lt;br /&gt;
:SD MPEG-4, WM9, H264,DivX; HD MPEG-2 (1080i), WM9(720p)&lt;br /&gt;
&lt;br /&gt;
*Audio: &lt;br /&gt;
:dual stereo (2.0 + 2.0),MPEG-1, Dolby AC-3&lt;br /&gt;
&lt;br /&gt;
[http://www.synnex.com.tw/oem/mic_link/seminar%20download/y70303.pdf Quelle Codecs]&lt;br /&gt;
&lt;br /&gt;
= Bezugsquellen = &lt;br /&gt;
&lt;br /&gt;
===Platinen:===&lt;br /&gt;
* [http://www.pollin.de/shop/dt/NzQ5OTA2OTk-/Bausaetze_Module/Module/Receiver_Mainboard_mit_Twin_DVB_T_Tuner.html Pollin : Receiver-Mainboard mit Twin DVB-T Tuner (390 052, 7,95€)]&lt;br /&gt;
* [http://www.pollin.de/shop/dt/NjQ5OTA2OTk-/Bausaetze_Module/Module/Receiver_Mainboard_mit_Twin_DVB_C_Tuner.html Pollin : Receiver-Mainboard mit Twin DVB-C Tuner (390 053, 7,95€)]&lt;br /&gt;
* [http://www.pollin.de/shop/dt/MzQxODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/RS232_Einbaubuchse.html Pollin : RS232-Einbaubuchse (721 856, 0,25€)]&lt;br /&gt;
* [http://www.pollin.de/shop/dt/NDQxODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/USB_2_0_Einbaubuchse.html Pollin : USB 2.0-Einbaubuchse (721 855, 0,25€)]&lt;br /&gt;
&lt;br /&gt;
===Zubehör:===&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NjUwOTQ2OTk-/Stromversorgung/Netzgeraete/Festspannungs_Netzgeraete/Schaltnetzteil_DELTA_EADP_50DF_12_V_4_16_A.html Pollin : Schaltnetzteil DELTA EADP-50DF, 12 V-/4,16 A (350 943 , 4,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MDg4OTM1OTk-/Bauelemente_Bauteile/Gehaeuse/Stahlblech_Gehaeuse_mit_Frontblende.html Pollin : Stahlblech-Gehäuse mit Frontblende (460 119, 2,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/Nzc5OTczOTk-/SAT_Antennentechnik/Satelliten_Technik/Fernbedienungen/Infrarot_Fernbedienung_RCX155.html Pollin : Infrarot-Fernbedienung RCX155 (620 022, 1,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NDY5ODgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/WLAN_miniPCI_Karte_XG_603.html Pollin : WLAN miniPCI-Karte XG-603 (711 035, 3,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MzQ3ODI0OTk-/SAT_Antennentechnik/Kabel/Antennen_Anschlusskabel_75_150_mm.html Pollin : Antennen-Anschlusskabel 75 Ω, 150 mm (571 256, 0,15€)]&lt;br /&gt;
*Pollin : SATA-Kabel, 2x SATA-Stecker, 0,35m (721 854, 0,50€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NDI1ODcyOTk-/Computer_und_Zubehoer/Hardware/Kabel_Stecker_Adapter/SATA_Stromversorgungsadapter.html Pollin : SATA-Stromversorgungsadapter (721 475, 0,85)]&lt;br /&gt;
*Pollin : PC-Stromversorgungskabel, 2x 5,25&amp;quot;- Stecker, 70mm (720 569, 0,20€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/MjUwOTgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/Wireless_LAN_Antennen_Adapterkabel.html Pollin : Wireless LAN Antennen-Adapterkabel (710 947, 4,95€)]&lt;br /&gt;
*[http://www.pollin.de/shop/dt/NjAwOTgyOTk-/Computer_und_Zubehoer/Netzwerktechnik/Wireless_LAN/Wireless_LAN_Rundstrahl_Antenne.html Pollin : Wireless LAN Rundstrahl-Antenne (710 993, 1,95€)]&lt;br /&gt;
&lt;br /&gt;
= Hardware =&lt;br /&gt;
== Daten ==&lt;br /&gt;
* Betriebsspannung 12 V-&lt;br /&gt;
* Stromaufnahme ohne HDD max. 2 A&lt;br /&gt;
* 2x Philips DVB-T Tuner TU1216L/IVP&lt;br /&gt;
* HDD-Stromversorgung on Board&lt;br /&gt;
* Anschlüsse extern: 2x Tuner In, 2x Tuner Out, LAN 10/100 Mbps, USB 2.0, optischer Audioausgang, AV-Out (Cinch), S-Video, 2x Scart&lt;br /&gt;
* interne Ports/Anschlüsse: 3x USB 2.0, 2x SATA, RS232, miniPCI für WLAN-Karte (XG-603), Smartcard-Reader, CI-Slot&lt;br /&gt;
&lt;br /&gt;
* Flash Hynix HY27US08121A 8bit 64MByte 2.7V - 3.6 Volt&lt;br /&gt;
&lt;br /&gt;
==Varianten==&lt;br /&gt;
===DVB-T===&lt;br /&gt;
===DVB-C===&lt;br /&gt;
&lt;br /&gt;
== Bilder/Innenleben ==&lt;br /&gt;
&#039;&#039;&#039;Gesamtansicht&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:moretv_1.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JTAG Anschluss für LPC921F (unter anderem) + Platz zur Montage einer 3,5&amp;quot; Festplatte&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:moretv_2.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Board komplett&#039;&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
[[Bild:moretv_3.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DVI - nicht bestückt&#039;&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
[[Bild:moretv_4.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DVB-T Tuner&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_5.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CPU RAM etc.&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_6.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;mini PCI, Sata, CI-Slot, Smartcard&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_7.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rückseite komplett&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_8.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CI Controller&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:moretv_9.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sata Controller&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_10.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RAM und TDA8024T SmartCard Interface&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_11.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LAN DP83816&#039;&#039;&#039; (fast identisch zu SiS 900)&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_12.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SW1 auf ON = SW-Update / SW2 auf ON = JTAG Enable&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_13.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stromversorgung&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_14.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anschluss J4&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:moretv_15.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EJTAG für den PNX8950&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:EJTAG.jpg|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wie man sieht, müssen keinerlei Jumper gesetzt sein, um DVB-T&#039;&#039;&#039; &lt;br /&gt;
&#039;&#039;&#039;empfangen zu können.&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:Tuner_Jumper1.JPG|700px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RS-232 Console auf J2&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:Console.png|268px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3,3Volt auf J4&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
[[Bild:lpc_8051_power.png|400px]]&lt;br /&gt;
&lt;br /&gt;
== Schnittstellen ==&lt;br /&gt;
&lt;br /&gt;
3x USB intern: (J30 USB Port4, J31 USB Port3, J46 USB Port2)&lt;br /&gt;
Pinout:&lt;br /&gt;
   &lt;br /&gt;
PIN4:GND/Schwarz, PIN3:D+/Grün, PIN2:D-/Weiss, Pin1:+5V/Rot&lt;br /&gt;
&lt;br /&gt;
== Chips ==&lt;br /&gt;
Übersicht über die verwendeten Bausteine mit Links auf ensprechende Datenblätter, Quellen etc.&lt;br /&gt;
&lt;br /&gt;
* Multimedia-CPU Philips PNX8950EH/M2/S1&lt;br /&gt;
**[http://datasheet.octopart.com/PNX8950EH/M2/S1%2C55-NXP-datasheet-8325175.pdf Datasheet PNX8950EH/M2/S1]&lt;br /&gt;
**[http://www.brightsign.biz/documents/HD2000HardwareGuide.pdf Brightsign Hardwareguide]&lt;br /&gt;
**[http://www.kanecomputing.co.uk/pdfs/mds_mds810.pdf MDS-810]&lt;br /&gt;
*[http://www.alldatasheet.com/datasheet-pdf/pdf/98585/SAMSUNG/K4H511638C-UCCC.html 4x 512 MBit DDR SDRAM SAMSUNG K4H511638C-UCCC]&lt;br /&gt;
* [http://www.hynix.com/datasheet/pdf/flash/HY27(U_S)S(08_16)121A%20Series(Rev1.3).pdf HYNIX HY27US08121A 512 Mbit NAND Flash]&lt;br /&gt;
* [http://www.siliconimage.com/docs/SiI-DS-0102-D.pdf SiI3512 SATA150 Controller]&lt;br /&gt;
*[http://www.national.com/ds/DP/DP83816.pdf 10/100 Mbps PCI Ethernet-Controller NATIONAL DP83816]&lt;br /&gt;
* High Speed USB PCI Host Controller Philips ISP1561BM [http://www.nxp.com/acrobat_download2/expired_datasheets/ISP1561_2.pdf Datasheet]&lt;br /&gt;
* [http://www.maxim-ic.com/datasheet/index.mvp/id/1068 MAX3222]&lt;br /&gt;
* PNX8510HW [http://www.datasheetcatalog.org/datasheet/philips/PNX8510_PNX8511_4.pdf Datasheet]&lt;br /&gt;
* Bedienteil mit LED-Display, Infrarotempfänger usw.&lt;br /&gt;
* In der DVB-C-Version: Philips CU1216 DVB-C Tuner [http://read.pudn.com/downloads138/sourcecode/others/589797/CU1216L-3-datasheet.pdf Datasheet]&lt;br /&gt;
** Philips TDA10023 (DVB-C Channel Decoder) [http://www.datasheetdownload.com/download.php?id=677273 Datasheet]&lt;br /&gt;
* In der DVB-T-Version: Philips TU1216 DVB-T Tuner&lt;br /&gt;
** Philips TDA10046 (DVB-T Channel Decoder) [http://www.nxp.com/acrobat/literature/9397/75009522.pdf Spec Sheet] [http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/dvb/frontends/tda1004x.c - linuxtv.org Frontend Treiber]&lt;br /&gt;
** Philips TDA6650 (5 V mixer/oscillator and low noise PLL synthesizer for hybrid terrestrial tuner) [http://www.nxp.com/documents/data_sheet/TDA6650TT_6651TT.pdf Datasheet] [http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/dvb/frontends/tda665x.c - linuxtv.org Tuner Treiber]&lt;br /&gt;
* Philips TDA8024T (IC Card Interface) [http://www.nxp.com/documents/data_sheet/TDA8024.pdf Datasheet]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nicht bestückte ICs:&lt;br /&gt;
* U42 DVI (?)&lt;br /&gt;
* U40 ????&lt;br /&gt;
* U41 ????&lt;br /&gt;
* U44 ????&lt;br /&gt;
* U45 ????&lt;br /&gt;
* U48 ????&lt;br /&gt;
* U51 ????&lt;br /&gt;
* U59 ????&lt;br /&gt;
&lt;br /&gt;
= Software =&lt;br /&gt;
Übersicht über verwendete Software (Betriebssysteme, Compiler, Tools, etc)&lt;br /&gt;
&lt;br /&gt;
* Bootloader&lt;br /&gt;
**Eventuell [http://www.denx.de/wiki/U-Boot/SourceCode U-Boot] support mit diesen 4 patches:&lt;br /&gt;
# [http://lists.denx.de/pipermail/u-boot/attachments/20061204/e9922ec2/attachment.obj pnx8550support.diff.gz]&lt;br /&gt;
# [http://lists.denx.de/pipermail/u-boot/attachments/20061206/556029b0/attachment.obj nxp_i2c.diff.gz]&lt;br /&gt;
#  [http://lists.denx.de/pipermail/u-boot/attachments/20061211/bff13619/attachment.obj nxp_pci.diff.gz]&lt;br /&gt;
# [http://lists.denx.de/pipermail/u-boot/attachments/20061211/8d42666e/attachment.obj mips_timer2.diff]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Overview&lt;br /&gt;
+The Silverbox is a development platform based on the NXP PNX8550&lt;br /&gt;
+(Nexperia) media processor.  It consists of a MIPS32 compatible PR4450&lt;br /&gt;
+core, accompanied by two TriMedia processors.  Typical use for the&lt;br /&gt;
+PNX8550 is in settop box and advanced analogue and digital TV sets.&lt;br /&gt;
+&lt;br /&gt;
+This first version of U-Boot for this platform supports a minimal set&lt;br /&gt;
+of commands and hardware.  Feature to be added in the near future are&lt;br /&gt;
+PCI bus, Ethernet, NAND flash and USB support.&lt;br /&gt;
+&lt;br /&gt;
+Boot Methods&lt;br /&gt;
+U-Boot for the Silverbox is typically loaded into SDRAM using an EJTAG&lt;br /&gt;
+probe.  The load address and entry point is 0xA0010000.&lt;br /&gt;
+&lt;br /&gt;
+As NAND flash support is not yet available a single page NAND flash&lt;br /&gt;
+loader is also not available.  This limits this U-Boot version, but&lt;br /&gt;
+a single page loader based on U-Boot 1.1.3 is available on request.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Screenshot der Windows CE 5.0 Oberfläche (über VNC mit der Box verbunden http://efonvnc.sourceforge.net/)&lt;br /&gt;
&lt;br /&gt;
[[Datei:CEscreenshot.png]]&lt;br /&gt;
&lt;br /&gt;
= Anwendungen und Ideen =&lt;br /&gt;
==Realisierte Projekte/Anwendungen==&lt;br /&gt;
==Anwendungsideen==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unter Linux:&#039;&#039;&#039;&lt;br /&gt;
Festplattenreceiver,&lt;br /&gt;
Asterisk Server,&lt;br /&gt;
NAS,&lt;br /&gt;
Car-PC,&lt;br /&gt;
Multimedia Client/Server,&lt;br /&gt;
Wetterstation logging Server,&lt;br /&gt;
Solar logging Server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unter WinCE&#039;&#039;&#039;:&lt;br /&gt;
Festplattenreceiver,&lt;br /&gt;
NAS,&lt;br /&gt;
Car-PC,&lt;br /&gt;
Media Portal Client/Server&lt;br /&gt;
&lt;br /&gt;
= weitergehende Infos im Netz =&lt;br /&gt;
Alles was noch weiterführende Infos bietet. Andere Wikis, Beiträge, etc.&lt;br /&gt;
&lt;br /&gt;
* [http://www.oohito.com/wince/mips_o_j.htm MIPS FTP Server]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=55393</id>
		<title>Minila Version MockUp</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=55393"/>
		<updated>2011-02-27T12:13:39Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &amp;lt;u&amp;gt;Bilder der Platine&amp;lt;/u&amp;gt; ==&lt;br /&gt;
=== &amp;lt;u&amp;gt;Gerenderte Platine&amp;lt;/u&amp;gt; ===&lt;br /&gt;
[[Bild:MockUpMiniLALayoutTop.jpg|400px]]&lt;br /&gt;
[[Bild:MockUpMiniLALayoutBottom.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Platine der Sammelbestellung bestückt&amp;lt;/u&amp;gt; ===&lt;br /&gt;
[[Bild:MockUpMiniLALayoutTopPrototyp.jpg|400px]]&lt;br /&gt;
[[Bild:MockUpMiniLALayoutBottomPrototyp.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;u&amp;gt;Informationen über den MiniLA&amp;lt;/u&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;CPLD&amp;lt;/u&amp;gt; ===&lt;br /&gt;
* wird der XC95288XL bleiben, da dies nur eine Veränderung und keine Neuentwicklung wird&lt;br /&gt;
* einige Signale werden an anderen Pins angeschlossen und verteilt&lt;br /&gt;
* TQFP144&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;RAM-Speicher&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;u&amp;gt;512K*32:&amp;lt;/u&amp;gt;&lt;br /&gt;
* 512K*32 Kanäle&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* GS816036 &lt;br /&gt;
* [http://de.farnell.com/gsi-technology/gs816032bgt-200/18m-synch-burst-sram-512kx32-smd/dp/1447526 Optional GS816032]&lt;br /&gt;
* [http://www.cypress.com/?mpn=CY7C1381D-133AXC  Optional CY7C1381D-133AX]&lt;br /&gt;
* wird in der Sammelbestellung verwendet&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;1M*32:&amp;lt;/u&amp;gt;&lt;br /&gt;
* 1M*32 Kanäle&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* CY7C1441AV33-133AXC/CY7C1441AV33-133AXI&lt;br /&gt;
* 60eur/stk&lt;br /&gt;
* dazu muss eine Brücke zwischen TP1 am CPLD und TP2 am SRAM eingelötet werden&lt;br /&gt;
[[Bild:MockUpMiniLALayout1MBitRAM.png|200px]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;USB&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Der FTDI FT2232D wird immer im Bus Powerd Modus betrieben und über USB versorgt.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Spannungsversorgung&amp;lt;/u&amp;gt; ===&lt;br /&gt;
* 3,3V, Versorgung über externe 5V bis 16V oder über den DCDC USB powered (Regler wird über den FTDI An/Aus geschaltet)&lt;br /&gt;
* 5V über DCDC (galvanisch getrennt) mit Spannungsregler dahinter oder DCDC überbrückt direkt über USB&lt;br /&gt;
&lt;br /&gt;
Dadurch kann der MiniLA mit einem Y-Kabel USB versorgt werden oder über ein externes Netzteil.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Galvanische Trennung&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Als Zusatzoption über den ADUM4160, einem DCDC-Wandler und einem zusätzlichem Spannungsregler.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Steckverbinder&amp;lt;/u&amp;gt; ===&lt;br /&gt;
* Steckerbelegung bleibt beim alten&lt;br /&gt;
* X1-7 wird entfernt, da eh wenig Platz im CPLD ist&lt;br /&gt;
* X8 bleibt erhalten&lt;br /&gt;
* K8 wird dann auch komplett entfernt, da nicht mehr benötigt (alle Signale sind auch an K1 verfügbar)&lt;br /&gt;
* Serienwiderstände in den Datenleitungen wie gehabt&lt;br /&gt;
* Tastköpfe extern wie gehabt (siehe auch: Platinen)&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;JTAG&amp;lt;/u&amp;gt; ===&lt;br /&gt;
* JTAG-Signale liegen an einem MicroMatch Steckverbinder an.&lt;br /&gt;
* Programmierung über FTDI und &amp;quot;xc3sprog&amp;quot; http://www.mikrocontroller.net/articles/MiniLA#via_USB&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Parallel Port&amp;lt;/u&amp;gt; ===&lt;br /&gt;
* nicht vorgesehen&lt;br /&gt;
* Signale liegen an einem MicroMatch Steckverbinder an&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;LEDs&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Je nach Wunsch in SMD 0805 oder als 5mm LED&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Gehäuse&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Passende Gehäusen:&lt;br /&gt;
* Hammond 1455L1602 (Mouser, RS, Conrad usw.)&lt;br /&gt;
* Fischer AKG 105 30 160 (RS, DK, Conrad usw.)&lt;br /&gt;
* Fischer AKG 105 34 160 (RS, DK, Conrad usw.)&lt;br /&gt;
* RFS RF-1599 (rfsupplier.com)&lt;br /&gt;
&lt;br /&gt;
Auch 3,5&amp;quot; USB/eSATA Festplatten-Geh​äuse sind bestens geeignet.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;u&amp;gt;Schaltplan und Layout&amp;lt;/u&amp;gt; ==&lt;br /&gt;
=== &amp;lt;u&amp;gt;Schaltplan&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&#039;&#039;&#039;Seite 1 &amp;amp; 2&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet1.png|350px]]&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet2.png|350px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Seite 3 &amp;amp; 4&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet3.png|350px]]&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet4.png|350px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Seite 5 &amp;amp; 6&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet5.png|350px]]&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet6.png|350px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Seite 7&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:MockUpMiniLASchaltplanSheet7.png|350px]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Layout&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&#039;&#039;&#039; Platine Mini-LA &#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleTop.png.png|350px]]&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleBottom.png|350px]]&lt;br /&gt;
* 2-lagig&lt;br /&gt;
* über den 5mm LEDs sind die SMD0805 LEDs angeordnet&lt;br /&gt;
* [[Datei:MiniLAVersionMockUpV1_05a.zip]]&lt;br /&gt;
* [[Datei:MiniLAVersionMockUpTeileliste.zip]]&lt;br /&gt;
&#039;&#039;&#039; &amp;lt;u&amp;gt;Platine Tastköpfe&amp;lt;/u&amp;gt; &#039;&#039;&#039;&lt;br /&gt;
* Sind über Wigbert zu beziehen. Er hat noch Tastköpfe von der ersten Sammelbestellung.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Steckverbinder auf der Platine&amp;lt;/u&amp;gt; ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Steckverbinder&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! || nicht gesteckt || gesteckt 1-2 || gesteckt 2-3&lt;br /&gt;
|-&lt;br /&gt;
| JP2  || - || Normal Modus || JTAG-Programmierung über FTDI&lt;br /&gt;
|-&lt;br /&gt;
| JP3  || - || Normal Modus || JTAG-Programmierung über FTDI&lt;br /&gt;
|-&lt;br /&gt;
| JP4  || - || Normal Modus || JTAG-Programmierung über FTDI&lt;br /&gt;
|-&lt;br /&gt;
| JP5  || - || Normal Modus || JTAG-Programmierung über FTDI&lt;br /&gt;
|-&lt;br /&gt;
| JP6  || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| JP7  || Platine &amp;quot;AUS&amp;quot; || Platine &amp;quot;AN&amp;quot; || -&lt;br /&gt;
|-&lt;br /&gt;
| JP9  || - || externe Versorgung || USB Versorgung&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
 JP6 - Spannungsversorgung für einen Externen Programmieradapter (&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&#039;&#039;&#039;nicht Brücken!&#039;&#039;&#039;&amp;lt;/span&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;u&amp;gt;Erste Inbetriebnahme&amp;lt;/u&amp;gt; ==&lt;br /&gt;
* 1. Platine liegt unangeschlossen (ohne USB und externe Versorgung) vor euch&lt;br /&gt;
* 2. Jumper JP7 stecken (USB-Interface wird mit Strom versorgt)&lt;br /&gt;
* 3. Jumper JP9 nicht stecken (CPLD wird erstmal nicht mit Strom versorgt, der Sicherheit halber)&lt;br /&gt;
* 4. USB-Kabel anschließen, LED7 sollte AN und LED8 Aus sein, FTDI sollte sich am PC anmelden&lt;br /&gt;
* 4.1 Wenn er nicht erkannt wird, Spannung über C45 ~9V, Spannung über C46 5V, Alles um IC4, IC5 und IC6 prüfen&lt;br /&gt;
* 5. [http://www.mikrocontroller.net/articles/Minila_Version_MockUp#FTDI FTDI-Treiber installieren]&lt;br /&gt;
* 6. [http://www.mikrocontroller.net/articles/Minila_Version_MockUp#LibUSB LibUSB installieren]&lt;br /&gt;
* 7. MiniLA vom PC trennen&lt;br /&gt;
* 8. [http://www.mikrocontroller.net/articles/Minila_Version_MockUp#Steckverbinder_auf_der_Platine JP9 nach Wahl stecken] &lt;br /&gt;
* 9. [http://www.mikrocontroller.net/articles/Minila_Version_MockUp#Steckverbinder_auf_der_Platine JP2-JP5] auf 2-3 stecken (wenn der USB-Stecker links, dann sind das die unteren Kontakte&lt;br /&gt;
*10. [http://www.mikrocontroller.net/articles/Minila_Version_MockUp#Firmware schon mal alles vorbereiten, in den Ordner wechseln, alles eintippen]&lt;br /&gt;
*11. eventuell externe Versorgung und USB-Kabel anstecken, LED8 sollte nun auch leuchten&lt;br /&gt;
*12. Enter drücken, CPLD sollte programmiert werden.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Der Spannungsregler für die 3,3V wird erst eingeschaltet wenn die USB-Verbindung steht und Windows den FTDI erkannt hat. LED8 leuchtet dann auch.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;u&amp;gt;Programmierung&amp;lt;/u&amp;gt; ==&lt;br /&gt;
[[Image:MiniLAVersionMockUpFTPROG1.png|thumb|150px|right|Programmierung des FTDIs, Bild1]][[Image:MiniLAVersionMockUpFTPROG2.png|thumb|150px|right|Programmierung des FTDIs, Bild2]]&lt;br /&gt;
=== &amp;lt;u&amp;gt;FTDI&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Zum Programmieren werden die [http://www.ftdichip.com/Drivers/D2XX.htm FTDI-Treiber für D2XX] und das Programm [http://www.ftdichip.com/Support/Utilities.htm FT_PROG] benötigt.&lt;br /&gt;
&lt;br /&gt;
*1. MiniLA über ein USB Kabel an den PC anschließen und die heruntergeladenen FTDI-Treiber Installieren&lt;br /&gt;
*2. Das Programm FT_PROG starten&lt;br /&gt;
*3. Im Programm auf &amp;quot;Scan and Parse&amp;quot; drücken (1)(Bild1)&lt;br /&gt;
*4. rechte Maustaste auf den erkannten FTDI, &amp;quot;Aply Template&amp;quot; und &amp;quot;From File&amp;quot; [http://www.mikrocontroller.net/attachment/95887/MiniLA.xml diese Datei] auswählen (2)(Bild1)&lt;br /&gt;
*5. Im Programm auf &amp;quot;Program Devices&amp;quot; drücken (3)(Bild1), ein neues Fenster öffnet sich (Bild2)&lt;br /&gt;
*6. Haken setzen (4)(Bild2)&lt;br /&gt;
*7. Auf &amp;quot;Program&amp;quot; drücken (5)(Bild2)&lt;br /&gt;
*8. MiniLA abstecken und wieder anklemmen&lt;br /&gt;
*9. Fertig&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;LibUSB&amp;lt;/u&amp;gt; ===&lt;br /&gt;
[[Image:MiniLAVersionMockUplibUSB1.png|thumb|150px|right|LibUSB einrichten, Bild1]][[Image:MiniLAVersionMockUplibUSB2.png|thumb|150px|right|LibUSB einrichten, Bild2]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&#039;&#039;&#039;Mit der [http://www.mikrocontroller.net/attachment/96598/xc3sprog.exe neuen xc3sprog Revision 483] ist LibUSB nicht mehr notwendig. Dieses greift direkt auf den FTDI-Treiber zu.&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
LibUSB funktioniert nur unter 32Bit Windows.&lt;br /&gt;
Zur Programmierung des CPLDs über xc3prog wurde LibUSB benötigt. Dies bekommt man [http://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/ hier]. Die letzte Version anklicken und dann &amp;quot;libusb-win32-bin-x.x.x.x.zip&amp;quot; herunterladen und entpacken.&lt;br /&gt;
*1. In den Ordner &amp;quot;bin&amp;quot; und &amp;quot;x86&amp;quot; für Windows XP 32Bit wechseln&lt;br /&gt;
*2. &amp;quot;install-filter-win.exe&amp;quot; starten&lt;br /&gt;
*3. &amp;quot;Install a device filter&amp;quot; und &amp;quot;Next&amp;quot; drücken&lt;br /&gt;
*4. In der Liste auf &amp;quot;USB Serial Converter A&amp;quot; drücken (1) und danach auf Install (2) (Bild1)&lt;br /&gt;
*5. In der Liste auf &amp;quot;USB Serial Converter B&amp;quot; drücken (3) und danach noch einmal auf Install (4) (Bild2)&lt;br /&gt;
*6. Mit &amp;quot;Cancel&amp;quot; (5) Abbrechen (Bild2)&lt;br /&gt;
*7. Fertig&lt;br /&gt;
&lt;br /&gt;
Es gibt im Forum auch eine Version von xc3sprog, die kein libusb benötigt http://www.mikrocontroller.net/topic/174860#1995201&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Firmware&amp;lt;/u&amp;gt; ===&lt;br /&gt;
[[Image:MiniLAVersionMockUpxc3prog.png|thumb|150px|right|Programmierung des CPLDs]]&lt;br /&gt;
Zum Programmieren wird [http://sourceforge.net/projects/xc3sprog/ xc3sprog] benötigt. [http://www.mikrocontroller.net/attachment/96598/xc3sprog.exe Hier eine angepasste Version (Mit der anderen gab es Probleme beim CPLD löschen).] &lt;br /&gt;
&lt;br /&gt;
*1. Auf dem MiniLA die Jumper JP2-JP5 in die Stellung [http://www.mikrocontroller.net/articles/Minila_Version_MockUp#Steckverbinder_auf_der_Platine 2-3] umstecken und den MiniLA anschließen. &lt;br /&gt;
*2. Kommandozeile öffnen&lt;br /&gt;
*3. In den Ordner wechseln, in der xc3prog und die jed-Datei liegt. (Die jed-Datei aus dem Archiv &amp;quot;Timeanalysis&amp;quot; bzw. &amp;quot;Stateanalysis&amp;quot; - siehe weiter unten - extrahieren. Sie ist im Ordner xilinx zu finden.)&lt;br /&gt;
*4. &amp;quot;xc3sprog -c ftdi -v miniLA.jed&amp;quot; eingeben und Enter drücken.&lt;br /&gt;
*5. Der FTDI sollte programmiert werden, ähnlich dem nebenstehendem Bild.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Hilfreiche Befehle&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* &amp;quot;xc3sprog -c ftdi -v -j&amp;quot; - Erkennung des CPLDs&lt;br /&gt;
* &amp;quot;xc3sprog -c ftdi -v -e&amp;quot; - Löschen des CPLDs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&#039;&#039;&#039;Die Firmware ist nur lauffähig mit der Version des MockUp MiniLAs und es sollte auch keine der originalen Firmwares verwendet werden, weil diese nicht kompatibel sind mit der neuen Hardware!!!&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
* [http://www.mikrocontroller.net/wikifiles/c/c0/MiniLAVersionMockUpFirmwareLEDTest.zip LED-Test] (Blinkfrequenz: ~6,0Hz, ~1,5Hz, ~0,4Hz)&lt;br /&gt;
* [http://www.mikrocontroller.net/wikifiles/f/f5/Fw_timeanalysis_v1.8_for_MockUp_miniLA.zip Timeanalysis v1.8]&lt;br /&gt;
* [http://www.mikrocontroller.net/wikifiles/2/27/Fw_stateanalysis_v2.3_for_MockUp_miniLA.zip Stateanalysis v2.3]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;LED-Bedeutungen&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! || LED1 || LED3 || LED5&lt;br /&gt;
|-&lt;br /&gt;
| nach dem Einschalten&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X || ||&lt;br /&gt;
|-&lt;br /&gt;
| Idle&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X || ||&lt;br /&gt;
|-&lt;br /&gt;
| Pre-Trigger&lt;br /&gt;
|| &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X || &lt;br /&gt;
|-&lt;br /&gt;
| Wait for Trigger || || &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X&lt;br /&gt;
|-&lt;br /&gt;
| Trigger || || &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X&lt;br /&gt;
|-&lt;br /&gt;
| Post-Trigger|| &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X ||&lt;br /&gt;
|-&lt;br /&gt;
| Transfer zum PC&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;u&amp;gt;Software&amp;lt;/u&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Minila Windows EXE Vers 0.6.4 für 256k und 512K Sample Speicher gibts hier&lt;br /&gt;
http://www.mikrocontroller.net/attachment/97534/minila.zip &amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: inpout32.dll | Programmbibliothek, welche für die Nutzung der Software benötigt wird]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/174860#new Hauptthread auf Mikrocontroller.net]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MiniLA Original]&lt;br /&gt;
* [http://minila.sourceforge.net/hw/other/bg/minila_bg_sch.pdf Schaltplan der alten Version]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Inpout32.zip&amp;diff=55392</id>
		<title>Datei:Inpout32.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Inpout32.zip&amp;diff=55392"/>
		<updated>2011-02-27T12:12:21Z</updated>

		<summary type="html">&lt;p&gt;Remote1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_Arithmetik8&amp;diff=54901</id>
		<title>AVR-Tutorial: Arithmetik8</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_Arithmetik8&amp;diff=54901"/>
		<updated>2011-02-09T14:48:52Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Die Umwandlung von Dezimal in das Binärsystem */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Eine der Hauptaufgaben eines Mikrokontrollers bzw. eines Computers allgemein, ist es, irgendwelche Berechnungen anzustellen. Der Löwenanteil an den meisten Berechnungen entfällt dabei auf einfache Additionen bzw. Subtraktionen. Multiplikationen bzw. Divisionen kommen schon seltener vor, bzw. können oft durch entsprechende Additionen bzw. Subtraktionen ersetzt werden. Weitergehende mathematische Konstrukte werden zwar auch ab und an benötigt, können aber in der Assemblerprogrammierung durch geschickte Umformungen oft vermieden werden.&lt;br /&gt;
&lt;br /&gt;
== Hardwareunterstützung ==&lt;br /&gt;
&lt;br /&gt;
Praktisch alle Mikroprozessoren unterstützen Addition und Subtraktion direkt in Hardware, das heißt: Sie haben eigene Befehle dafür. Einige bringen auch Unterstützung für eine Hardwaremultiplikation mit (so zum Beispiel der [[ATmega8]]), während Division in Hardware schon seltener zu finden ist.&lt;br /&gt;
&lt;br /&gt;
== 8 Bit versus 16 Bit ==&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt des Tutorials wird gezielt auf 8 Bit Arithmetik eingegangen, um zunächst die Grundlagen des Rechnens mit einem µC zu zeigen. Die Erweiterung von 8 Bit auf 16 Bit Arithmetik ist in einigen Fällen wie Addition und Subtraktion trivial, kann sich aber bei Multiplikation und Division in einem beträchtlichen Codezuwachs niederschlagen.&lt;br /&gt;
&lt;br /&gt;
Der im Tutorial verwendete ATmega8 besitzt eine sog. 8-Bit Architektur. Das heißt, dass seine Rechenregister (mit Ausnahmen) nur 8 Bit breit sind und sich daher eine 8-Bit Arithmetik als die natürliche Form der Rechnerei auf diesem Prozessor anbietet. Berechnungen, die mehr als 8 Bit erfordern, müssen dann durch Kombinationen von Rechenvorgängen realisiert werden. Eine Analogie wäre z.&amp;amp;nbsp;B. das Rechnen, wie wir alle es in der Grundschule gelernt haben. Auch wenn wir in der Grundschule (in den Anfängen) nur die Additionen mit Zahlen kleiner als 10 auswendig gelernt haben, so können wir dennoch durch die Kombination von mehreren derartigen Additionen beliebig große Zahlen addieren. Das gleiche gilt für Multiplikationen. In der Grundschule musste wohl jeder von uns das &#039;Kleine Einmaleins&#039; auswendig lernen, um Multiplikationen im Zahlenraum bis 100 quasi &#039;in Hardware&#039; zu berechnen. Und doch können wir durch Kombinationen solcher Einfachmultiplikationen und zusätzlichen Additionen in beliebig große Zahlenräume vorstoßen.&lt;br /&gt;
&lt;br /&gt;
Die Einschränkung auf 8 Bit ist also keineswegs eine Einschränkung in dem Sinne, dass es eine prinzipielle Obergrenze für Berechnungen gäbe. Sie bedeutet lediglich eine obere Grenze dafür, bis zu welchen Zahlen in einem Rutsch gerechnet werden kann. Alles, was darüber hinausgeht, muss dann mittels Kombinationen von Berechnungen gemacht werden.&lt;br /&gt;
&lt;br /&gt;
== 8-Bit Arithmetik ohne Berücksichtigung eines Vorzeichens ==&lt;br /&gt;
&lt;br /&gt;
Die Bits des Registers besitzen dabei eine Wertigkeit, die sich aus der Stelle des Bits im Byte ergibt. Dies ist völlig analog zu dem uns vertrauten Dezimalsystem. Auch dort besitzt eine Ziffer in einer Zahl eine bestimmte Wertigkeit, je nach dem, an welcher Position diese Ziffer in der Zahl auftaucht. So hat z.&amp;amp;nbsp;B. die Ziffer 1 in der Zahl 12 die Wertigkeit &#039;Zehn&#039;, während sie in der Zahl 134 die Wertigkeit &#039;Hundert&#039; besitzt. Und so wie im Dezimalsystem die Wertigkeit einer Stelle immer das Zehnfache der Wertigkeit der Stelle unmittelbar rechts von ihr ist, so ist im Binärsystem die Wertigkeit einer Stelle immer das 2-fache der Stelle rechts von ihr.&lt;br /&gt;
&lt;br /&gt;
Die Zahl 4632 im Dezimalsystem kann also so aufgefasst werden:&lt;br /&gt;
&lt;br /&gt;
   4632  =     4 * 1000          ( 1000 = 10 hoch 3 )&lt;br /&gt;
            +  6 * 100           (  100 = 10 hoch 2 )&lt;br /&gt;
            +  3 * 10            (   10 = 10 hoch 1 )&lt;br /&gt;
            +  2 * 1             (    1 = 10 hoch 0 )&lt;br /&gt;
&lt;br /&gt;
=== Die Umwandlung von Binär in das Dezimalystem ===&lt;br /&gt;
&lt;br /&gt;
Völlig analog ergibt sich daher folgendes für z.&amp;amp;nbsp;B. die 8 Bit Binärzahl &amp;lt;b&amp;gt;0b10011011&amp;lt;/b&amp;gt; (um Binärzahlen von Dezimalzahlen zu unterscheiden, wird ein &amp;lt;b&amp;gt;0b&amp;lt;/b&amp;gt; vorangestellt):&lt;br /&gt;
&lt;br /&gt;
  0b10011011     =    1 * 128    ( 128 = 2 hoch 7 )&lt;br /&gt;
                   +  0 * 64     (  64 = 2 hoch 6 )&lt;br /&gt;
                   +  0 * 32     (  32 = 2 hoch 5 )&lt;br /&gt;
                   +  1 * 16     (  16 = 2 hoch 4 )&lt;br /&gt;
                   +  1 * 8      (   8 = 2 hoch 3 )&lt;br /&gt;
                   +  0 * 4      (   4 = 2 hoch 2 )&lt;br /&gt;
                   +  1 * 2      (   2 = 2 hoch 1 )&lt;br /&gt;
                   +  1 * 1      (   1 = 2 hoch 0 )&lt;br /&gt;
&lt;br /&gt;
Ausgerechnet (um die entsprechende Dezimalzahl zu erhalten) ergibt das&lt;br /&gt;
128 + 16 + 8 + 2 + 1 = 155. Die Binärzahl &amp;lt;b&amp;gt;0b10011011&amp;lt;/b&amp;gt; entspricht also der Dezimalzahl &amp;lt;b&amp;gt;155&amp;lt;/b&amp;gt;. Es ist wichtig, sich klar zu machen, dass es zwischen Binär- und Dezimalzahlen keinen grundsätzlichen Unterschied gibt. Beides sind nur verschiedene Schreibweisen für das Gleiche: Eine Zahl. Während wir Menschen an das Dezimalsystem gewöhnt sind, ist das Binärsystem für einen Computer geeigneter, da es nur aus den 2 Ziffern 0 und 1 besteht, welche sich leicht in einem Computer darstellen lassen (Spannung, keine Spannung).&lt;br /&gt;
&lt;br /&gt;
Welches ist nun die größte Zahl, die mit 8 Bit dargestellt werden kann? Dabei handelt es sich offensichtlich um die Zahl &amp;lt;b&amp;gt;0b11111111&amp;lt;/b&amp;gt;. In Dezimalschreibweise wäre das die Zahl&lt;br /&gt;
&lt;br /&gt;
    0b11111111   =   1  *  128&lt;br /&gt;
                   + 1  *  64&lt;br /&gt;
                   + 1  *  32&lt;br /&gt;
                   + 1  *  16&lt;br /&gt;
                   + 1  *  8&lt;br /&gt;
                   + 1  *  4&lt;br /&gt;
                   + 1  *  2&lt;br /&gt;
                   + 1  *  1&lt;br /&gt;
&lt;br /&gt;
oder ausgerechnet: &amp;lt;b&amp;gt;255&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird also mit 8 Bit Arithmetik betrieben, wobei alle 8 Bit als signifikante Ziffern benutzt werden (also kein Vorzeichenbit, dazu später mehr), so kann damit im Zahlenraum &amp;lt;b&amp;gt;0&amp;lt;/b&amp;gt; bis &amp;lt;b&amp;gt;255&amp;lt;/b&amp;gt; gerechnet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    Binär          Dezimal               Binär         Dezimal&lt;br /&gt;
&lt;br /&gt;
   0b00000000        0                 0b10000000       128&lt;br /&gt;
   0b00000001        1                 0b10000001       129&lt;br /&gt;
   0b00000010        2                 0b10000010       130&lt;br /&gt;
   0b00000011        3                 0b10000011       131&lt;br /&gt;
   0b00000100        4                 0b10000100       132&lt;br /&gt;
   0b00000101        5                 0b10000101       133&lt;br /&gt;
     ...                                      ...&lt;br /&gt;
   0b01111100      124                 0b11111100       252&lt;br /&gt;
   0b01111101      125                 0b11111101       253&lt;br /&gt;
   0b01111110      126                 0b11111110       254&lt;br /&gt;
   0b01111111      127                 0b11111111       255&lt;br /&gt;
&lt;br /&gt;
=== Die Umwandlung von Dezimal in das Binärsystem ===&lt;br /&gt;
&lt;br /&gt;
Aus dem vorhergehenden ergibt sich völlig zwanglos die Vorschrift, wie Binärzahlen ins Dezimalsystem umgewandelt werden können (nicht vergessen: Die Zahl selber wird ja gar nicht verändert. Binär- und Dezimalsystem sind ja nur verschiedene Schreibweisen): Durch Anwendung der Vorschrift, wie denn eigentlich ein Stellenwertsystem aufgebaut ist.&lt;br /&gt;
Aber wie macht man den umgekehrten Schritt, die Wandlung vom Dezimal ins Binärsystem. Der Weg führt über die Umkehrung des vorhergehenden Prinzips. Fortgesetzte Division durch 2&lt;br /&gt;
&lt;br /&gt;
Es sei die Zahl 92 ins Binärsystem zu wandeln.&lt;br /&gt;
&lt;br /&gt;
     92 / 2   =   46   Rest 0&lt;br /&gt;
     46 / 2   =   23   Rest 0&lt;br /&gt;
     23 / 2   =   11   Rest 1&lt;br /&gt;
     11 / 2   =    5   Rest 1&lt;br /&gt;
      5 / 2   =    2   Rest 1&lt;br /&gt;
      2 / 2   =    1   Rest 0&lt;br /&gt;
      1 / 2   =    0   Rest 1&lt;br /&gt;
&lt;br /&gt;
Die Division wird solange durchgeführt, bis sich ein Divisionergebnis von 0 ergibt. Die Reste, von unten nach oben gelesen, ergeben dann die Binärzahl. Die zu 92 gehörende Binärzahl lautet also 1011100. Es wird noch eine führende 0 ergänzt um sie auf die standardmässigen 8-Bit zu bringen: &amp;lt;b&amp;gt;0b01011100&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 8-Bit Arithmetik mit Berücksichtigung eines Vorzeichens ==&lt;br /&gt;
&lt;br /&gt;
Soll mit Vorzeichen (also positiven und negativen Zahlen) gerechnet werden, so erhebt sich die Frage: Wie werden eigentlich positive bzw. negative Zahlen dargestellt? Alles was wir haben sind ja 8 Bit in einem Byte.&lt;br /&gt;
&lt;br /&gt;
=== Problem der Kodierung des Vorzeichens ===&lt;br /&gt;
&lt;br /&gt;
Die Lösung des Problems besteht darin, dass ein Bit zur Anzeige des Vorzeichens benutzt wird. Im Regelfall wird dazu das am weitesten links stehende Bit benutzt. Von den verschiedenen Möglichkeiten, die sich hiermit bieten, wird in der Praxis fast ausschließlich mit dem sog. 2-er Komplement gearbeitet, da es Vorteile bei der Addition bzw. Subtraktion von Zahlen bringt. In diesem Fall muß nämlich das Vorzeichen einer Zahl überhaupt nicht berücksichtigt werden. Durch die Art und Weise der Bildung von negativen Zahlen kommt am Ende das Ergebnis mit dem korrekten Vorzeichen heraus.&lt;br /&gt;
&lt;br /&gt;
=== 2-er Komplement ===&lt;br /&gt;
&lt;br /&gt;
Das 2-er Komplement verwendet das höchstwertige Bit eines Byte, das sog. MSB (= &amp;lt;b&amp;gt;M&amp;lt;/b&amp;gt;ost &amp;lt;b&amp;gt;S&amp;lt;/b&amp;gt;ignificant &amp;lt;b&amp;gt;B&amp;lt;/b&amp;gt;it) zur Anzeige des Vorzeichens. Ist dieses Bit 0, so ist die Zahl positiv. Ist es 1, so handelt es sich um eine negative Zahl. Die 8-Bit Kombination &amp;lt;b&amp;gt;0b10010011&amp;lt;/b&amp;gt; stellt also eine negative Zahl dar, &amp;lt;b&amp;gt;wenn und nur wenn diese Bitkombination überhaupt als vorzeichenbehaftete Zahl aufgefasst werden soll&amp;lt;/b&amp;gt;. Anhand der Bitkombination alleine ist es also nicht möglich, eine definitive Aussage zu treffen, ob es sich um eine vorzeichenbehaftete Zahl handelt oder nicht. Erst wenn durch den Zusammenhang klar ist, dass man es mit vorzeichenbehafteten Zahlen zu tun hat, bekommt das MSB die Sonderbedeutung des Vorzeichens.&lt;br /&gt;
&lt;br /&gt;
Um bei einer Zahl das Vorzeichen zu wechseln, geht man wie folgt vor:&lt;br /&gt;
* Zunächst wird das 1-er Komplement gebildet, indem alle Bits umgedreht werden. Aus 0 wird 1 und aus 1 wird 0&lt;br /&gt;
* Danach wird aus diesem Zwischenergebnis das 2-er Komplement gebildet, indem noch 1 addiert wird.&lt;br /&gt;
&lt;br /&gt;
Diese Vorschrift kann immer dann benutzt werden, wenn das Vorzeichen einer Zahl gewechselt werden soll. Er macht aus positiven Zahlen negative und aus negativen Zahlen positive.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; Es soll die Binärdarstellung für -92 gebildet werden. Dazu benötigt man zunächst die Binärdarstellung für +92, welche &amp;lt;b&amp;gt;0b01011100&amp;lt;/b&amp;gt; lautet. Diese wird jetzt nach der Vorschrift für 2-er Komplemente negiert und damit negativ gemacht.&lt;br /&gt;
&lt;br /&gt;
   0b01011100            Ausgangszahl&lt;br /&gt;
   0b10100011            1-er Komplement, alle Bits umdrehen&lt;br /&gt;
   0b10100100            noch 1 addieren&lt;br /&gt;
&lt;br /&gt;
Die Binärdarstellung für -92 lautet also &amp;lt;b&amp;gt;0b10100100&amp;lt;/b&amp;gt;. Das gesetzte MSB weist diese Binärzahl auch tatsächlich als negative Zahl aus.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; Gegeben sei die Binärzahl &amp;lt;b&amp;gt;0b00111000&amp;lt;/b&amp;gt;, welche als vorzeichenbehaftete Zahl anzusehen ist. Welcher Dezimalzahl entspricht diese Binärzahl?&lt;br /&gt;
&lt;br /&gt;
Da das MSB nicht gesetzt ist, handelt es sich um eine positive Zahl und die Umrechnung kann wie im Fall der vorzeichenlosen 8-Bit Zahlen erfolgen. Das Ergebnis lautet also +56 ( = 0 * 128 + 0 * 64 + 1 * 32 + 1 * 16 + 1 * 8 + 0 * 4 + 0 * 2 + 0 * 1 )&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; Gegeben sei die Binärzahl &amp;lt;b&amp;gt;0b10011001&amp;lt;/b&amp;gt;, welche als vorzeichenbehaftete Zahl anzusehen ist. Welcher Dezimalzahl entspricht diese Binärzahl?&lt;br /&gt;
&lt;br /&gt;
Da das MSB gesetzt ist, handelt es sich um eine negative Zahl. Daher wird diese Zahl zunächst negiert um dadurch eine positive Zahl zu erhalten.&lt;br /&gt;
&lt;br /&gt;
    0b10011001       Originalzahl&lt;br /&gt;
    0b01100110       1-er Komplement, alle Bits umdrehen&lt;br /&gt;
    0b01100111       2-er Komplement, noch 1 addiert&lt;br /&gt;
&lt;br /&gt;
Die zu 0b10011001 gehörende positive Binärzahl lautet also 0b01100111. Da es sich um eine positive Zahl handelt, kann sie wiederum ganz normal, wie vorzeichenlose Zahlen, in eine Dezimalzahl umgerechnet werden. Das Ergebnis lautet 103 ( = 0 * 128 + 1 * 64 + 1 * 32 + 0 * 16 + 0 * 8 + 1 * 4 + 1 * 2 + 1 * 1). Da aber von einer negativen Zahl ausgegangen wurde, ist &amp;lt;b&amp;gt;0b10011001&amp;lt;/b&amp;gt; die binäre Darstellung der Dezimalzahl -103.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; Gegeben sei dieselbe Binärzahl &amp;lt;b&amp;gt;0b10011001&amp;lt;/b&amp;gt;. Aber diesmal sei sie als vorzeichenlose Zahl aufzufassen. Welcher Dezimalzahl entspricht diese Binärzahl?&lt;br /&gt;
&lt;br /&gt;
Da die Binärzahl als vorzeichenlose Zahl aufzufassen ist, hat das MSB keine spezielle Bedeutung. Die Umrechnung erfolgt also ganz normal: 0b10011001 = 1 * 128 + 0 * 64 + 0 * 32 + 1 * 16 + 1 * 8 + 0 * 4 + 0 * 2 + 1 * 1 = 153.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; Wie lautet die Binärzahl zu -74?&lt;br /&gt;
&lt;br /&gt;
Da es sich hier offensichtlich im eine vorzeichenbehaftete Zahl handelt, müssen die Regeln des 2-er Komplemnts angewendet werden. Zunächst ist also die Binärrepräsentierung von +74 zu bestimmen, welche dann durch Anwendung des 2-er Komplements negiert wird.&lt;br /&gt;
&lt;br /&gt;
  74 / 2 = 37  Rest 0&lt;br /&gt;
  37 / 2 = 18  Rest 1&lt;br /&gt;
  18 / 2 =  9  Rest 0&lt;br /&gt;
   9 / 2 =  4  Rest 1&lt;br /&gt;
   4 / 2 =  2  Rest 0&lt;br /&gt;
   2 / 2 =  1  Rest 0&lt;br /&gt;
   1 / 2 =  0  Rest 1&lt;br /&gt;
&lt;br /&gt;
Die Binärdarstellung für +74 lautet daher &amp;lt;b&amp;gt;0b01001010&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    0b01001010     +74&lt;br /&gt;
    0b10110101     1-er Komplement, alle Bits umdrehen&lt;br /&gt;
    0b10110110     noch 1 addieren&lt;br /&gt;
&lt;br /&gt;
Die Binärdarstellung für -74 lautet daher &amp;lt;b&amp;gt;0b10110110&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arithmetikflags ==&lt;br /&gt;
&lt;br /&gt;
Im Statusregister des Prozessors gibt es eine Reihe von Flags, die durch Rechenergebnisse beeinflusst werden, bzw. in Berechnungen einfließen können.&lt;br /&gt;
&lt;br /&gt;
=== Carry ===&lt;br /&gt;
Das Carry-Flag &#039;&#039;&#039;C&#039;&#039;&#039; zeigt an, ob bei einer Berechnung mit vorzeichenlosen Zahlen ein Über- oder Unterlauf erfolgt ist, d.h. das Ergebnis der Berechnung liegt außerhalb des darstellbaren Bereiches 0...255.&lt;br /&gt;
&lt;br /&gt;
Wie das?&lt;br /&gt;
&lt;br /&gt;
Angenommen es müssen zwei 8-Bit-Zahlen addiert werden.&lt;br /&gt;
&lt;br /&gt;
    10100011&lt;br /&gt;
  + 11110011&lt;br /&gt;
   ---------&lt;br /&gt;
   110010110&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Addition umfasst neun Bit und liegt außerhalb des in einem Register darstellbaren Zahlenbereiches 0...255; die Addition &#039;&#039;ist übergelaufen&#039;&#039;.  Werden dieselben Zahlen subtrahiert,&lt;br /&gt;
&lt;br /&gt;
    10100011&lt;br /&gt;
  - 11110011&lt;br /&gt;
   ---------&lt;br /&gt;
    10110000&lt;br /&gt;
&lt;br /&gt;
verbleibt an der höchstwertigsten Stelle ein &amp;quot;geborgtes&amp;quot; Bit, welches durch das Carry angezeigt wird.&lt;br /&gt;
&lt;br /&gt;
=== Signed- und Overflowflag ===&lt;br /&gt;
Wird mit vorzeichenbehafteten Zahlen gerechnet, so wird das Verlassen des 8-Bit-Zahlenbereiches -128...+127 durch die Flags &#039;&#039;&#039;S&#039;&#039;&#039; und &#039;&#039;&#039;V&#039;&#039;&#039; angezeigt. Der Prozessor selbst unterscheidet nicht zwischen vorzeichenlosen und -behafteten Zahlen. Der Programmierer legt durch Wahl der ausgewerteten Flags (C bei vorzeichenlosen bzw. S/V bei vorzeichenbehafteten) die Interpretation der Zahlen fest.&lt;br /&gt;
&lt;br /&gt;
=== Weitere Flags ===&lt;br /&gt;
Das Zero-Flag &#039;&#039;&#039;Z&#039;&#039;&#039; wird gesetzt, wenn das 8-Bit-Ergebnis der Berechnung null ist. Dies kann bei der Addition auch durch Überlauf geschehen, was durch zusätzliches Carryflag angezeigt wird.&lt;br /&gt;
&lt;br /&gt;
Das Negative-Flag &#039;&#039;&#039;N&#039;&#039;&#039; wird gesetzt, wenn im Ergebnis das höchstwertige Bit gesetzt ist. Bei vorzeichenbehafteter Arithmetik ist dies als negative Zahl zu interpretieren, sofern nicht durch das V-Flag ein Verlassen des Zahlbereichs angezeigt wird.&lt;br /&gt;
&lt;br /&gt;
Das Half-Carry-Flag &#039;&#039;&#039;H&#039;&#039;&#039; zeigt, analog zum Carry-Flag, einen Übertrag zwischen Bit 3 und 4 an. Dies kann in speziellen Anwendungen (z.&amp;amp;nbsp;B. zwei simultane Vier-Bit-Berechnungen mit einem Befehl) nützlich sein.&lt;br /&gt;
&lt;br /&gt;
=== Übersicht über die arithmetischen Flags ===&lt;br /&gt;
&lt;br /&gt;
Ergebnis des Befehls &#039;&#039;&#039;ADD Rd, Rr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
          Rr|    0 |    1 |   64 |  127 |  128 |  129 |  192 |  255&lt;br /&gt;
   Rd       |(  +0)|(  +1)|( +64)|(+127)|(-128)|(-127)|( -64)|(  -1)&lt;br /&gt;
  ----------+------+------+------+------+------+------+------+------&lt;br /&gt;
    0 (  +0)|    Z |      |      |      |S N   |S N   |S N   |S N&lt;br /&gt;
    1 (  +1)|      |      |      | VN   |S N   |S N   |S N   |   CZ&lt;br /&gt;
   64 ( +64)|      |      | VN   | VN   |S N   |S N   |   CZ |   C&lt;br /&gt;
  127 (+127)|      | VN   | VN   | VN   |S N   |   CZ |   C  |   C&lt;br /&gt;
  128 (-128)|S N   |S N   |S N   |S N   |SV CZ |SV C  |SV C  |SV C&lt;br /&gt;
  129 (-127)|S N   |S N   |S N   |   CZ |SV C  |SV C  |SV C  |S NC&lt;br /&gt;
  192 ( -64)|S N   |S N   |   CZ |   C  |SV C  |SV C  |S NC  |S NC&lt;br /&gt;
  255 (  -1)|S N   |   CZ |   C  |   C  |SV C  |S NC  |S NC  |S NC&lt;br /&gt;
&lt;br /&gt;
Man erkennt: C=1 genau dann wenn die Addition Rd + Rr mit vorzeichenlosen Zahlen überläuft.  V=1 genau dann wenn die Addition mit vorzeichenbehafteten Zahlen überläuft.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ergebnis des Befehls &#039;&#039;&#039;SUB Rd, Rr&#039;&#039;&#039; bzw. &#039;&#039;&#039;CP Rd, Rr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
          Rr|    0 |   63 |   64 |  127 |  128 |  191 |  192 |  255&lt;br /&gt;
   Rd       |(  +0)|( +63)|( +64)|(+127)|(-128)|( -65)|( -64)|(  -1)&lt;br /&gt;
  ----------+------+------+------+------+------+------+------+------&lt;br /&gt;
    0 (  +0)|    Z |S NC  |S NC  |S NC  | VNC  |   C  |   C  |   C&lt;br /&gt;
   63 ( +63)|      |    Z |S NC  |S NC  | VNC  | VNC  |   C  |   C&lt;br /&gt;
   64 ( +64)|      |      |    Z |S NC  | VNC  | VNC  | VNC  |   C&lt;br /&gt;
  127 (+127)|      |      |      |    Z | VNC  | VNC  | VNC  | VNC&lt;br /&gt;
  128 (-128)|S N   |SV    |SV    |SV    |    Z |S NC  |S NC  |S NC&lt;br /&gt;
  191 ( -65)|S N   |S N   |SV    |SV    |      |    Z |S NC  |S NC&lt;br /&gt;
  192 ( -64)|S N   |S N   |S N   |SV    |      |      |    Z |S NC&lt;br /&gt;
  255 (  -1)|S N   |S N   |S N   |S N   |      |      |      |    Z&lt;br /&gt;
&lt;br /&gt;
Man erkennt: C=1 genau dann wenn die Subtraktion Rd - Rr mit vorzeichenlosen Zahlen unterläuft; äquivalent dazu ist Rd &amp;lt; Rr (vorzeichenlos).  S=1 genau dann wenn die Subtraktion mit vorzeichenbehafteten Zahlen unterläuft bzw. Rd &amp;gt; Rr (vorzeichenbehaftet).&lt;br /&gt;
&lt;br /&gt;
== Inkrementieren / Dekrementieren ==&lt;br /&gt;
&lt;br /&gt;
Erstaunlich viele Operationen in einem Computer-Programm entfallen auf die Operationen &#039;Zu einer Zahl 1 addieren&#039; bzw. &#039;Von einer Zahl 1 subtrahieren&#039;. Dementsprechend enthalten die meisten Mikroprozessoren die Operationen &#039;&#039;Inkrementieren&#039;&#039; (um 1 erhöhen) bzw. &#039;&#039;Dekrementieren&#039;&#039; (um 1 verringern) als eigenständigen Assemblerbefehl. So auch der ATmega8.&lt;br /&gt;
&lt;br /&gt;
=== AVR-Befehle ===&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
        inc  r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
        dec  r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Operation ist einfach zu verstehen. Das jeweils angegebene Register (hier wieder am Register r16 gezeigt) wird um 1 erhöht bzw. um 1 verringert. Dabei wird die Zahl im Register als vorzeichenlose Zahl angesehen. Enthält das Register bereits die größtmögliche Zahl (0b11111111 oder dezimal 255), so erzeugt ein weiteres Inkrementieren die kleinstmögliche Zahl (0b00000000 oder dezimal 0) bzw. umgekehrt dekrementiert 0 zu 255.&lt;br /&gt;
&lt;br /&gt;
== Addition ==&lt;br /&gt;
Auf einem Mega8 gibt es nur eine Möglichkeit, um eine Addition durchzuführen: Die beiden zu addierenden Zahlen müssen in zwei Registern stehen.&lt;br /&gt;
&lt;br /&gt;
=== AVR-Befehle ===&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
     add  r16, r17      ; Addition der Register r16 und r17. Das Ergebnis wird&lt;br /&gt;
                        ; im Register r16 abgelegt&lt;br /&gt;
     adc  r16, r17      ; Addition der Register r16 und r17, wobei das Carry-Bit&lt;br /&gt;
                        ; noch zusätzlich mit addiert wird.&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei der Addition zweier Register wird ein möglicher Überlauf in allen Fällen im Carry Bit abgelegt. Daraus erklärt sich dann auch das Vorhandensein eines Additionsbefehls, der das Carry-Bit noch zusätzlich mitaddiert: Man benötigt ihn zum Aufbau einer Addition die mehr als 8 Bit umfasst. Die niederwertigsten Bytes werden mit einem &amp;lt;b&amp;gt;add&amp;lt;/b&amp;gt; addiert und alle weiteren höherwertigen Bytes werden, vom Niederwertigsten zum Höchstwertigsten, mittels &amp;lt;b&amp;gt;adc&amp;lt;/b&amp;gt; addiert. Dadurch werden eventuelle Überträge automatisch berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
== Subtraktion ==&lt;br /&gt;
Subtraktionen können auf einem AVR in zwei unterschiedlichen Arten ausgeführt werden. Entweder es werden zwei Register voneinander subtrahiert oder es wird von einem Register eine konstante Zahl abgezogen. Beide Varianten gibt es wiederrum in den Ausführungen mit und ohne Berücksichtigung des Carry Flags&lt;br /&gt;
&lt;br /&gt;
=== AVR-Befehle ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
     sub  r16, r17      ; Subtraktion des Registers r17 von r16. Das Ergebnis wird&lt;br /&gt;
                        ; im Register r16 abgelegt&lt;br /&gt;
     sbc  r16, r17      ; Subtraktion des Registers r17 von r16, wobei das Carry-Bit&lt;br /&gt;
                        ; noch zusätzlich mit subtrahiert wird. Das Ergebnis wird&lt;br /&gt;
                        ; im Register r16 abgelegt&lt;br /&gt;
     subi r16, zahl     ; Die Zahl (als Konstante) wird vom Register r16 subtrahiert.&lt;br /&gt;
                        ; Das Ergebnis wird im Register r16 abgelegt&lt;br /&gt;
     sbci r16, zahl     ; Subtraktion einer konstanten Zahl vom Register r16, wobei&lt;br /&gt;
                        ; zusätzlich noch das Carry-Bit mit subtrahiert wird.&lt;br /&gt;
                        ; Das Ergebnis wird im Register r16 abgelegt.&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Multiplikation ==&lt;br /&gt;
Multiplikation kann auf einem AVR je nach konkretem Typ auf zwei unterschiedliche Arten ausgeführt werden. Während die größeren ATMega Prozessoren über einen Hardwaremultiplizierer verfügen, ist dieser bei den kleineren Tiny Prozessoren nicht vorhanden. Hier muß die Multiplikation quasi zu Fuß durch entsprechende Addition von Teilresultaten erfolgen.&lt;br /&gt;
&lt;br /&gt;
=== Hardwaremultiplikation ===&lt;br /&gt;
Vorzeichenbehaftete und vorzeichenlose Zahlen werden unterschiedlich multipliziert. Denn im Falle eines Vorzeichens darf ein gesetztes 7. Bit natürlich nicht in die eigentliche Berechnung mit einbezogen werden. Statt dessen steuert dieses Bit (eigentlich die beiden MSB der beiden beteiligten Zahlen) das Vorzeichen des Ergebnisses. Die Hardwaremultiplikation ist auch dahingehend eingeschränkt, dass das Ergebnis einer Multiplikation immer in den Registerpärchen &#039;&#039;r0&#039;&#039; und &#039;&#039;r1&#039;&#039; zu finden ist. Dabei steht das LowByte (also die unteren 8 Bit) des Ergebnisses in &#039;&#039;r0&#039;&#039; und das HighByte in &#039;&#039;r1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== AVR-Befehl ====&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    mul   r16, r17      ; multipliziert r16 mit r17. Beide Registerinhalte werden&lt;br /&gt;
                        ; als vorzeichenlose Zahlen aufgefasst.&lt;br /&gt;
                        ; Das Ergebnis der Multiplikation ist in den Registern r0 und r1&lt;br /&gt;
                        ; zu finden.&lt;br /&gt;
&lt;br /&gt;
    muls  r16, r17      ; multipliziert r16 mit r17. Beide Registerinhalte werden&lt;br /&gt;
                        ; als vorzeichenbehaftete Zahlen aufgefasst.&lt;br /&gt;
                        ; Das Ergebnis der Multiplikation ist in den Registern r0 und r1&lt;br /&gt;
                        ; zu finden und stellt ebenfalls eine vorzeichenbehaftete&lt;br /&gt;
                        ; Zahl dar.&lt;br /&gt;
&lt;br /&gt;
    mulsu r16, r17      ; multipliziert r16 mit r17, wobei r16 als vorzeichenbehaftete&lt;br /&gt;
                        ; Zahl aufgefasst wird und r17 als vorzeichenlose Zahl.&lt;br /&gt;
                        ; Das Ergebnis der Multiplikation ist in den Registern r0 und r1&lt;br /&gt;
                        ; zu finden und stellt eine vorzeichenbehaftete Zahl dar.&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiplikation in Software ===&lt;br /&gt;
Multiplikation in Software ist nicht weiter schwierig. Man erinnere sich daran, wie Multiplikationen in der Grundschule gelehrt wurden:&lt;br /&gt;
Zunächst stand da das kleine Einmal-Eins, welches auswendig gelernt wurde. Mit diesen Kenntnissen konnten dann auch größere Multiplikationen angegangen werden, indem der Multiplikand mit jeweils einer Stelle des Multiplikators multipliziert wurde und die Zwischenergebnisse, geeignet verschoben, addiert wurden. Die Verschiebung um eine Stelle entspricht dabei einer Multiplikation mit 10.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; Zu multiplizieren sei 3456 * 7812&lt;br /&gt;
&lt;br /&gt;
       3456     * 7812&lt;br /&gt;
       ---------------&lt;br /&gt;
      24192     &amp;lt;-+|||&lt;br /&gt;
  +    27648    &amp;lt;--+||&lt;br /&gt;
  +      3456   &amp;lt;---+|&lt;br /&gt;
  +       6912  &amp;lt;----+&lt;br /&gt;
      --------&lt;br /&gt;
      26998272&lt;br /&gt;
&lt;br /&gt;
Im Binärsystem funktioniert Multiplikation völlig analog. Nur ist hier das kleine Einmaleins sehr viel einfacher! Es gibt nur 4 Multiplikationen (anstatt 100 im Dezimalsystem):&lt;br /&gt;
&lt;br /&gt;
    0 * 0   = 0&lt;br /&gt;
    0 * 1   = 0&lt;br /&gt;
    1 * 0   = 0&lt;br /&gt;
    1 * 1   = 1&lt;br /&gt;
&lt;br /&gt;
Es gibt lediglich einen kleinen Unterschied gegenüber dem Dezimalsystem: Anstatt zunächst alle Zwischenergebnisse aufzulisten und erst danach die Summe zu bestimmen, werden wir ein neues Zwischenergebnis gleich in die Summe einrechnen. Dies deshalb, da Additionen von mehreren Zahlen im Binärsystem im Kopf sehr leicht zu Flüchtigkeitsfehlern führen (durch die vielen 0-en und 1-en). Weiters wird eine einfache Tatsache benutzt: 1 mal eine Zahl ergibt wieder die Zahl, während 0 mal eine Zahl immer 0 ergibt. Dadurch braucht man im Grunde bei einer Multiplikation überhaupt nicht zu multiplizieren, sondern eigentlich nur die Entscheidung treffen: Muss die Zahl geeignet verschoben addiert werden oder nicht?&lt;br /&gt;
&lt;br /&gt;
    0b00100011         * 0b10001001&lt;br /&gt;
    --------------------------------&lt;br /&gt;
      00100011          &amp;lt;--+|||||||&lt;br /&gt;
 +     00000000         &amp;lt;---+||||||&lt;br /&gt;
      ---------              ||||||&lt;br /&gt;
      001000110              ||||||&lt;br /&gt;
 +      00000000        &amp;lt;----+|||||&lt;br /&gt;
      ----------              |||||&lt;br /&gt;
      0010001100              |||||&lt;br /&gt;
 +       00000000       &amp;lt;-----+||||&lt;br /&gt;
      -----------              ||||&lt;br /&gt;
      00100011000              ||||&lt;br /&gt;
 +        00100011      &amp;lt;------+|||&lt;br /&gt;
      ------------              |||&lt;br /&gt;
      001001010011              |||&lt;br /&gt;
 +         00000000     &amp;lt;-------+||&lt;br /&gt;
      -------------              ||&lt;br /&gt;
      0010010100110              ||&lt;br /&gt;
 +          00000000    &amp;lt;--------+|&lt;br /&gt;
      --------------              |&lt;br /&gt;
      00100101001100              |&lt;br /&gt;
 +           00100011   &amp;lt;---------+&lt;br /&gt;
      ---------------&lt;br /&gt;
      001001010111011&lt;br /&gt;
&lt;br /&gt;
Man sieht auch, wie bei der Multiplikation zweier 8 Bit Zahlen sehr schnell ein 16 Bit Ergebnis entsteht. Dies ist auch der Grund, warum die Hardwaremultiplikation immer 2 Register zur Aufnahme des Ergebnisses benötigt.&lt;br /&gt;
&lt;br /&gt;
Ein Assembler Code, der diese Strategie im wesentlichen verwirklicht, sieht z.&amp;amp;nbsp;B. so aus. Dieser Code wurde nicht auf optimale Laufzeit getrimmt, sondern es soll im Wesentlichen eine 1:1 Umsetzung des oben gezeigten Schemas sein. Einige der verwendeten Befehle wurden im Rahmen dieses Tutorials an dieser Stelle noch nicht besprochen. Speziell die Schiebe- (&amp;lt;b&amp;gt;lsl&amp;lt;/b&amp;gt;) und Rotier- (&amp;lt;b&amp;gt;rol&amp;lt;/b&amp;gt;) Befehle sollten in der AVR Befehlsübersicht genau studiert werden, um ihr Zusammenspiel mit dem Carry Flag zu verstehen. Nur soviel als Hinweis: Das Carry Flag dient in der &amp;lt;b&amp;gt;lsl&amp;lt;/b&amp;gt; / &amp;lt;b&amp;gt;rol&amp;lt;/b&amp;gt; Sequenz als eine Art Zwischenspeicher, um das höherwertigste Bit aus dem Register r0 beim Verschieben in das Register r1 verschieben zu können. Der &amp;lt;b&amp;gt;lsl&amp;lt;/b&amp;gt; verschiebt alle Bits des Registers um 1 Stelle nach links, wobei das vorhergehende MSB ins Carry Bit wandert und rechts ein 0-Bit nachrückt. Der &amp;lt;b&amp;gt;rol&amp;lt;/b&amp;gt; verschiebt ebenfalls alle Stellen eines Registers um 1 Stelle nach links. Diesmal wird aber rechts nicht mit einem 0-Bit aufgefüllt, sondern an dieser Stelle wird der momentane Inhalt des Carry Bits eingesetzt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ldi  r16, 0b00100011  ; Multiplikator&lt;br /&gt;
    ldi  r17, 0b10001001  ; Multiplikand&lt;br /&gt;
                          ; Berechne r16 * r17&lt;br /&gt;
&lt;br /&gt;
    ldi  r18, 8          ; 8 mal verschieben und gegebenenfalls addieren&lt;br /&gt;
    clr  r19             ; 0 wird für die 16 Bit Addition benötigt&lt;br /&gt;
    clr  r0              ; Ergebnis Low Byte auf 0 setzen&lt;br /&gt;
    clr  r1              ; Ergebnis High Byte auf 0 setzen&lt;br /&gt;
&lt;br /&gt;
mult:&lt;br /&gt;
    lsl  r0              ; r1:r0 einmal nach links verschieben&lt;br /&gt;
    rol  r1&lt;br /&gt;
    lsl  r17             ; Das MSB von r17 ins Carry schieben&lt;br /&gt;
    brcc noadd           ; Ist dieses MSB (jetzt im Carry) eine 1?&lt;br /&gt;
    add  r0,r16          ; Wenn ja, dann r16 zum Ergebnis addieren&lt;br /&gt;
    adc  r1,r19&lt;br /&gt;
&lt;br /&gt;
noadd:&lt;br /&gt;
    dec  r18             ; Wurden alle 8 Bit von r17 abgearbeitet?&lt;br /&gt;
    brne mult            ; Wenn nicht, dann ein erneuter Verschiebe/Addier Zyklus&lt;br /&gt;
&lt;br /&gt;
                         ; r0 enthält an dieser Stelle den Wert 0b10111011&lt;br /&gt;
                         ; r1 enthält 0b00010010&lt;br /&gt;
                         ; Gemeinsam bilden r1 und r0 also die Zahl&lt;br /&gt;
                         ; 0b0001001010111011&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Division ==&lt;br /&gt;
Anders als bei der Multiplikation, gibt es auch auf einem ATMega-Prozessor keine hardwaremässige Divisionseinheit. Divisionen müssen also in jedem Fall mit einer speziellen Routine, die im wesentlichen auf Subtraktionen beruht, erledigt werden.&lt;br /&gt;
=== Division in Software ===&lt;br /&gt;
&lt;br /&gt;
Um die Vorgangsweise bei der binären Division zu verstehen, wollen wir wieder zunächst anhand der gewohnten dezimalen Division untersuchen wie sowas abläuft.&lt;br /&gt;
&lt;br /&gt;
Angenommen es soll dividiert werden: 938 / 4 ( 938 ist der Dividend, 4 ist der Divisor)&lt;br /&gt;
&lt;br /&gt;
Wie haben Sie es in der Grundschule gelernt? Wahrscheinlich so wie der Autor auch:&lt;br /&gt;
&lt;br /&gt;
    938 : 4 = 234&lt;br /&gt;
   ---&lt;br /&gt;
   -8&lt;br /&gt;
   ----&lt;br /&gt;
    1&lt;br /&gt;
    13&lt;br /&gt;
   -12&lt;br /&gt;
    ---&lt;br /&gt;
     1&lt;br /&gt;
     18&lt;br /&gt;
    -16&lt;br /&gt;
     --&lt;br /&gt;
      2 Rest&lt;br /&gt;
&lt;br /&gt;
Der Vorgang war: Man nimmt die erste Stelle des Dividenden (9) und ruft seine gespeicherte Einmaleins Tabelle ab, um festzustellen, wie oft der Divisor in dieser Stelle enthalten ist. In diesem konkreten Fall ist die erste Stelle 9 und der Divisor 4. 4 ist in 9 zweimal enthalten. Also ist 2 die erste Ziffer des Ergebnisses. 2 mal 4 ergibt aber 8 und diese 8 werden von den 9 abgezogen, übrig bleibt 1.&lt;br /&gt;
Aus dem Dividenden wird die nächste Ziffer (3) heruntergezogen und man erhält mit der 1 aus dem vorhergehenden Schritt 13.&lt;br /&gt;
Wieder dasselbe Spiel: Wie oft ist 4 in 13 enthalten? 3 mal (3 ist die nächste Ziffer des Ergebnisses) und 3 * 4 ergibt 12. Diese 12 von den 13 abgezogen macht 1. Zu dieser 1 gesellt sich wieder die nächste Ziffer des Dividenden, 8, um so 18 zu bilden.&lt;br /&gt;
Wie oft ist 4 in 18 enthalten? 4 mal (4 ist die nächste Ziffer des Ergebnisses), denn 4 mal 4 macht 16, und das von den 18 abgezogen ergibt 2.&lt;br /&gt;
Da es keine nächste Ziffer im Dividenden mehr gibt, lautet also das Resultat:&lt;br /&gt;
938 : 4 ergibt 234 und es bleiben 2 Rest.&lt;br /&gt;
&lt;br /&gt;
Die binäre Division funktioniert dazu völlig analog. Es gibt nur einen kleinen Unterschied, der einem sogar das Leben leichter macht. Es geht um den Schritt: Wie oft ist x in y enthalten?&lt;br /&gt;
Dieser Schritt ist in der binären Division besonders einfach, da das Ergebnis dieser Fragestellung nur 0 oder 1 sein kann. Das bedeutet aber auch: Entweder ist der Divisior in der zu untersuchenden Zahl enthalten, oder er ist es nicht. Das kann aber ganz leicht entschieden werden: Ist die Zahl größer oder gleich dem Divisior, dann ist der Divisor enthalten und zum Ergebnis kann eine 1 hinzugefügt werden. Ist die Zahl kleiner als der Divisior, dann ist der Divisior nicht enthalten und die nächste Ziffer des Ergebnisses ist eine 0.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Es soll die Division 0b01101100 : 0b00001001 ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Es wird wieder mit der ersten Stelle begonnen und die oben ausgeführte Vorschrift angewandt.&lt;br /&gt;
&lt;br /&gt;
   0b01101101 : 0b00001001 = 0b00001100&lt;br /&gt;
                               ^^^^^^^^&lt;br /&gt;
                               ||||||||&lt;br /&gt;
     0                ---------+|||||||   1001 ist in 0 0-mal enthalten&lt;br /&gt;
    -0                          |||||||&lt;br /&gt;
    --                          |||||||&lt;br /&gt;
     0                          |||||||&lt;br /&gt;
     01               ----------+||||||   1001 ist in 1 0-mal enthalten&lt;br /&gt;
    - 0                          ||||||&lt;br /&gt;
     --                          ||||||&lt;br /&gt;
     01                          ||||||&lt;br /&gt;
     011              -----------+|||||   1001 ist in 11 0-mal enthalten&lt;br /&gt;
    -  0                          |||||&lt;br /&gt;
     ---                          |||||&lt;br /&gt;
     011                          |||||&lt;br /&gt;
     0110             ------------+||||   1001 ist in 110 0-mal enthalten&lt;br /&gt;
    -   0                          ||||&lt;br /&gt;
     ----                          ||||&lt;br /&gt;
     0110                          ||||&lt;br /&gt;
     01101            -------------+|||   1001 ist in 1101 1-mal enthalten&lt;br /&gt;
    - 1001                          |||&lt;br /&gt;
     -----                          |||&lt;br /&gt;
      0100                          |||&lt;br /&gt;
      01001           --------------+||   1001 ist in 1001 1-mal enthalten&lt;br /&gt;
     - 1001                          ||&lt;br /&gt;
      -----                          ||&lt;br /&gt;
      00000                          ||&lt;br /&gt;
      000000          ---------------+|   1001 ist in 0 0-mal enthalten&lt;br /&gt;
    -      0                          |&lt;br /&gt;
      ------                          |&lt;br /&gt;
      0000001         ----------------+   1001 ist in 1 0-mal enthalten&lt;br /&gt;
     -      0&lt;br /&gt;
      -------&lt;br /&gt;
            1 Rest&lt;br /&gt;
&lt;br /&gt;
Die Division liefert also das Ergebnis 0b00001100, wobei ein Rest von 1 bleibt. Der Dividend 0b01101101 entspricht der Dezimalzahl 109, der Divisor 0b00001001 der Dezimalzahl 9. Und wie man sich mit einem Taschenrechner leicht überzeugen kann, ergibt die Division von 109 durch 9 einen Wert von 12, wobei 1 Rest bleibt. Die Binärzahl für 12 lautet 0b00001100, das Ergebnis stimmt also.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ldi  r16, 109   ; Dividend&lt;br /&gt;
    ldi  r17,   9   ; Divisor&lt;br /&gt;
&lt;br /&gt;
                    ; Division r16 : r17&lt;br /&gt;
&lt;br /&gt;
    ldi  r18,   8   ; 8 Bit Division&lt;br /&gt;
    clr  r19        ; Register für die Zwischenergebnisse / Rest&lt;br /&gt;
    clr  r20        ; Ergebnis&lt;br /&gt;
&lt;br /&gt;
divloop:&lt;br /&gt;
    lsl  r16        ; Zwischenergebnis mal 2 nehmen und das&lt;br /&gt;
    rol  r19        ; nächste Bit des Dividenden anhängen&lt;br /&gt;
&lt;br /&gt;
    lsl  r20        ; das Ergebnis auf jeden Fall mal 2 nehmen,&lt;br /&gt;
                    ; das hängt effektiv eine 0 an das Ergebnis an.&lt;br /&gt;
                    ; Sollte das nächste Ergebnis-Bit 1 sein, dann wird&lt;br /&gt;
                    ; diese 0 in Folge durch eine 1 ausgetauscht&lt;br /&gt;
&lt;br /&gt;
    cp   r19, r17   ; ist der Divisor größer?&lt;br /&gt;
    brlo div_zero   ; wenn nein, dann bleibt die 0&lt;br /&gt;
    sbr  r20, 1     ; wenn ja, dann jetzt die 0 durch eine 1 austauschen ...&lt;br /&gt;
    sub  r19, r17   ; ... und den Divisor abziehen&lt;br /&gt;
&lt;br /&gt;
div_zero:&lt;br /&gt;
    dec  r18        ; das Ganze 8 mal wiederholen&lt;br /&gt;
    brne divloop&lt;br /&gt;
&lt;br /&gt;
                    ; in r20 steht das Ergebnis der Division&lt;br /&gt;
                    ; in r19 steht der bei der Division entstehende Rest&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arithmetik mit mehr als 8 Bit ==&lt;br /&gt;
&lt;br /&gt;
Es gibt eine [[AVR_Arithmetik|Sammlung von Algorithmen zur AVR-Arithmetik]] mit mehr als 8 Bit, deren Grundprinzipien im wesentlichen identisch zu den in diesem Teil ausgeführten Prinzipien sind.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
{{Navigation_zurückhochvor|&lt;br /&gt;
zurücktext=Logik|&lt;br /&gt;
zurücklink=AVR-Tutorial: Logik|&lt;br /&gt;
hochtext=Inhaltsverzeichnis|&lt;br /&gt;
hochlink=AVR-Tutorial|&lt;br /&gt;
vortext=Stack|&lt;br /&gt;
vorlink=AVR-Tutorial: Stack}}&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR-Tutorial]]&lt;br /&gt;
[[Kategorie:AVR-Arithmetik]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=54439</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=54439"/>
		<updated>2011-01-21T09:22:20Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende Textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Baudrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 28.12.2010.zip | Software Stand 28.12.2010 (Bugfix in sms_decode behoben)]]&amp;lt;br&amp;gt; [[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum Versenden von SMS mit BASCOM und Delphi]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53831</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53831"/>
		<updated>2010-12-28T13:33:03Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 28.12.2010.zip | Software Stand 28.12.2010 (Bugfix in sms_decode behoben)]]&amp;lt;br&amp;gt; [[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum Versenden von SMS mit BASCOM und Delphi]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53830</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53830"/>
		<updated>2010-12-28T13:32:49Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 28.12.2010.zip | Software Stand 28.12.2010 (Bugfix in sms_decode)]]&amp;lt;br&amp;gt; [[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum Versenden von SMS mit BASCOM und Delphi]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53829</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53829"/>
		<updated>2010-12-28T13:31:45Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 28.12.2010.zip | Software Stand 28.12.2010]]&amp;lt;br&amp;gt; [[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum Versenden von SMS mit BASCOM und Delphi]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53828</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53828"/>
		<updated>2010-12-28T13:31:22Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 28.12.2010.zip | Software Stand 28.12.2010]]&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum Versenden von SMS mit BASCOM und Delphi]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Software_Stand_28.12.2010.zip&amp;diff=53827</id>
		<title>Datei:Software Stand 28.12.2010.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Software_Stand_28.12.2010.zip&amp;diff=53827"/>
		<updated>2010-12-28T13:30:58Z</updated>

		<summary type="html">&lt;p&gt;Remote1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53826</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=53826"/>
		<updated>2010-12-28T13:30:39Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 28.12.2010.zip | Software Stand 28.12.2010]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum Versenden von SMS mit BASCOM und Delphi]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51111</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51111"/>
		<updated>2010-10-04T06:55:27Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Allgmeine Quellen zum Thema */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets and language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51110</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51110"/>
		<updated>2010-10-04T06:52:04Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51109</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51109"/>
		<updated>2010-10-04T06:51:48Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,    /**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51108</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51108"/>
		<updated>2010-10-04T06:51:23Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51107</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=51107"/>
		<updated>2010-10-04T06:48:51Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Einleitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Lumberg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versand]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Elektronik.zip&amp;diff=50014</id>
		<title>Datei:Elektronik.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Elektronik.zip&amp;diff=50014"/>
		<updated>2010-08-19T13:19:12Z</updated>

		<summary type="html">&lt;p&gt;Remote1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Elektronik_Lagerverwaltung&amp;diff=50013</id>
		<title>Elektronik Lagerverwaltung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Elektronik_Lagerverwaltung&amp;diff=50013"/>
		<updated>2010-08-19T13:16:12Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Allgemeine Infos ==&lt;br /&gt;
&lt;br /&gt;
Verwaltung von elektronischen Bauteilen. Speichermöglichkeit von&lt;br /&gt;
Bildern, anlegen von Gehäuse, Bestellungs-Verwaltung, Stückzahlen und&lt;br /&gt;
Preise. Unterstützt unterschiedliche Datenbank-Systeme, so kann es auch&lt;br /&gt;
mit mehreren Rechnern gleichzeitig benutzt werden (Client/Server,&lt;br /&gt;
MySQL).&lt;br /&gt;
&lt;br /&gt;
* Bauteile&lt;br /&gt;
* Gehäuse&lt;br /&gt;
* Lieferanten&lt;br /&gt;
* Bestellvorschlag&lt;br /&gt;
* Typunterscheidung&lt;br /&gt;
* Suche&lt;br /&gt;
* Drucken&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
&lt;br /&gt;
[[Media: Elektronik.zip | aktuelle Version]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks, Foren, Communities ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/186629 Diskussion zum Artikel]&lt;br /&gt;
* [http://www.mmvisual.de Homepage Autor]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Elektronik_Lagerverwaltung&amp;diff=50012</id>
		<title>Elektronik Lagerverwaltung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Elektronik_Lagerverwaltung&amp;diff=50012"/>
		<updated>2010-08-19T13:14:43Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Allgemeine Infos ==&lt;br /&gt;
&lt;br /&gt;
Verwaltung von elektronischen Bauteilen. Speichermöglichkeit von&lt;br /&gt;
Bildern, anlegen von Gehäuse, Bestellungs-Verwaltung, Stückzahlen und&lt;br /&gt;
Preise. Unterstützt unterschiedliche Datenbank-Systeme, so kann es auch&lt;br /&gt;
mit mehreren Rechnern gleichzeitig benutzt werden (Client/Server,&lt;br /&gt;
MySQL).&lt;br /&gt;
&lt;br /&gt;
* Bauteile&lt;br /&gt;
* Gehäuse&lt;br /&gt;
* Lieferanten&lt;br /&gt;
* Bestellvorschlag&lt;br /&gt;
* Typunterscheidung&lt;br /&gt;
* Suche&lt;br /&gt;
* Drucken&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Elektronik.zip | aktuelle Version]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks, Foren, Communities ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/186629 Diskussion zum Artikel]&lt;br /&gt;
* [http://www.mmvisual.de Homepage Autor]&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_TWI&amp;diff=49671</id>
		<title>AVR TWI</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_TWI&amp;diff=49671"/>
		<updated>2010-08-03T13:40:44Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Grundlagen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von Alexander Starke&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Das TWI (Two Wire Interface) ist begründet durch seinen Aufbau ideal auf typische Mikrocontroller Applikationen zugeschnitten. Durch seinen 7 Bit breiten Adressraum können bis zu 128 (2&amp;lt;sup&amp;gt;7&amp;lt;/sup&amp;gt; = 128) Geräte miteinander verschaltet werden. Im Gegensatz zum SPI ([[Serial Peripheral Interface]]) werden nur zwei Busleitungen benötigt. Eine dient der Bereitstellung des Taktes (SCL) und die andere dem Datentransport (SDA). Die einzige zusätzlich benötigt Hardware besteht aus zwei Pull-Up Widerständen, welche von jeweils einer Busleitung gegen Vcc (5V) geschalten werden. Da alle Bustreiber mit offenem Kollektor bzw. Drain am Bus anliegen, ergibt sich eine logische UND-Verknüpfung. D.h., sobald irgendein Gerät auf einer der Busleitungen Low-Pegel anlegt, liegt automatisch die gesamte Busleitung auf Low. Der BUS hat nur High-Pegel, wenn alle angeschlossenen Geräte auch High-Pegel an ihrer entsprechenden Schnittstelle haben.&lt;br /&gt;
&lt;br /&gt;
Genau wie beim SPI initiiert auch beim TWI der Master den Datentransfer und beendet selbigen auch wieder. Gestartet wird eine Transmission durch eine Start-Bedingung und entsprechend beendet durch eine Stop-Bedingung. Während einer Transmission gilt der Bus als &amp;quot;busy&amp;quot; (beschäftigt) und kein anderer Master darf versuchen, Kontrolle über ihn zu erlangen. Einzige Ausnahme bildet hier der Fall, dass vor einer Stop-Bedingung durch den gerade aktiven Master noch eine zusätzliche Start-Bedingung auf den Bus gegeben wird. Dieser Fall tritt normalerweise dann ein, wenn der Master noch weitere Daten zu versenden hat und nicht die Kontrolle über den Bus verlieren möchte. Nach solch einem wiederholten Start (Repeated Start) ist der Bus wieder beschäftigt, bis zum nächsten Stop.&lt;br /&gt;
Start- und Stop-Bedingungen werden signalisiert, indem der Pegel der SDA-Leitung wechselt, während SCL High-Pegel hat.&lt;br /&gt;
&lt;br /&gt;
Alle Adresspakete auf dem TWI Bus haben eine Länge von 9 Bit. Davon beinhalten 7 Bit wie bereits eingangs erwähnt die Adresse der angesprochenen Komponente. Zusätzlich gibt es noch ein Bit, dass darüber bestimmt, ob ein Lese- oder ein Schreibzugriff durchgeführt werden soll (R/W=1 -&amp;gt; Lesen; RW=0 -&amp;gt; Schreiben). Das 9 Bit dient der Bestätigung. Wenn ein Slave bemerkt, dass er angesprochen wird, so bestätigt er dies, indem er mit dem 9. Taktzyklus (ACK) von SCL SDA auf Low-Pegel legt. Sollte der angesprochene Slave aus irgendwelchen Gründen nicht antworten können, so sollte SDA auf H-Pegel bleiben. Der Master hat dann die Wahl, ob er ein Stop sendet oder einen wiederholten Start durchführt.&lt;br /&gt;
&lt;br /&gt;
* SLA +R   --&amp;gt;    Adresspaket mit einer Slave-Adresse und einem Lese-Bit&lt;br /&gt;
* SLA +W  --&amp;gt;    Adresspaket mit einer Slave-Adresse und einem Schreib-Bit&lt;br /&gt;
&lt;br /&gt;
Das höchstwertige Bit wird prinzipiell zuerst übertragen (MSB Most Significant Bit). Die Slave-Adressen können durch den Anwender frei gewählt werden, nur 0000 000 ist reserviert, hiermit werden alle Slaves angesprochen. Wird ein solcher Zugriff durchgeführt, so sollten alle Slaves im ACK-Zyklus SDA auf L-Pegel legen.&lt;br /&gt;
Benutzt wird diese Aktion, wenn der Master die selben Daten an mehrere Slaves senden möchte. Sinn macht die Verwendung nur in Verbindung mit dem Schreib-Bit. Ein Setzen des Lese-Bits hätte zur Folge, dass verschiedene Slaves ja verschiedene Daten auf den Bus stellen könnten, was zu einem Durcheinander führen würde. Wird das Schreib-Bit gesetzt, so setzen im ACK-Zyklus alle Slaves SDA auf L-Pegel, welche den allgemeinen Adressaufruf erhalten und ausgewertet haben (also die nicht beschäftigt waren). Die folgenden Datenpakete werden dann von allen Slaves empfangen, welche SDA auf L-Pegel gelegt hatten.&lt;br /&gt;
&lt;br /&gt;
Alle Datenpakete auf dem TWI-Bus haben analog zu den Adresspaketen 9 Bit. Hiervon sind 8 Datenbits. Das 9. dient der Bestätigung. Während einer Datenübertragung ist es Aufgabe des Masters, den Takt, das Start- und das Stopzeichen bereitzustellen. Aufgabe des Empfängers ist die Bestätigung der erhaltenen Daten, indem er die SDA-Leitung während des 9. SCL-Zyklus auf L-Pegel legt. Dieses wird als ACK bezeichnet (Acknowledge). Bleibt SDA auf H-Pegel, so wird dem Sender signalisiert, dass die gesendeten Daten nicht empfangen wurden (NACK). Das MSB wird zuerst übertragen.&lt;br /&gt;
&lt;br /&gt;
Wenn man nun Adress- und Datenpakete kombiniert, hat man schon eine fertige Transmission. Diese besteht aus:&lt;br /&gt;
&lt;br /&gt;
* START    --&amp;gt;    SLA R/W    --&amp;gt;    ein oder mehr Datenpakete    --&amp;gt;    STOP&lt;br /&gt;
&lt;br /&gt;
Ein START gefolgt von einem STOP ist nicht zulässig. Wenn der Takt des Masters für den Slave zu schnell ist oder er noch mehr Zeit zur Bearbeitung braucht, so kann er SCL einfach länger auf L-Pegel halten. Die Verlängerung der L-Phase von SCL hat allerdings keinen Einfluss auf die Länge der H-Phase, da diese vom Master zur Verfügung gestellt wird. Dadurch kann es allerdings zu einer Reduzierung des Datentransfers kommen.&lt;br /&gt;
&lt;br /&gt;
== Multi-Master-Bussysteme ==&lt;br /&gt;
&lt;br /&gt;
Das TWI-Bussystem erlaubt den Multi-Master Betrieb. Es wurden spezielle Vorkehrungen getroffen, so dass auch wenn mehrere Master zur selben Zeit eine Transmission beginnen wollen keine Probleme auftreten und der Bus normal funktioniert. Nur die zwei folgenden Probleme sollten beachtet werden:&lt;br /&gt;
&lt;br /&gt;
# Es ist Sache des Anwenders, seine Algorithmen so auszulegen, dass in diesem Fall nur ein Master seine Transmission fortsetzt. Alle anderen Master sollten ihre Transmission sofort abbrechen. Diesen Auswahlprozess zwischen den Mastern nennt man Arbitrierung (Entscheidung). Wenn ein Master bemerkt, dass er den Entscheidungsprozess (die Arbitrierung) verloren hat, sollte er sofort in den Slave-Modus gehen, da es sein kann, dass der Master welcher den Prozess gewonnen hat ihn adressieren will. Die Tatsache, dass mehrere Master versucht hatten, eine Übertragung zu starten, sollte für die Slaves nicht feststellbar sein, die Daten auf dem Bus dürfen nicht beschädigt sein.&lt;br /&gt;
# Da verschiedene Master mit verschiedenen Taktfrequenzen auf dem Bus arbeiten könnten, ist eine Festlegung zu treffen, wie man diese synchronisiert. Dieses erleichtert auch den Arbitrierungsprozess.&lt;br /&gt;
&lt;br /&gt;
Diese Lösung dieses Problems stellt die schon oben angesprochene UND-Verknüpfung aller Komponenten auf dem Bus dar. So werden alle seriellen Taktraten der einzelnen Master UND verknüpft. Somit ergibt sich ein High-Pegel entsprechend dem des Masters mit dem kürzesten H-Pegel, der Low-Pegel ist durch den Master mit der geringsten Taktrate gegeben.&lt;br /&gt;
&lt;br /&gt;
Da der Multi-Master Betrieb für meine Anwendung keinen Belang hat, werde ich hier nicht näher darauf eingehen.&lt;br /&gt;
&lt;br /&gt;
==Aufbau des TWI==&lt;br /&gt;
&lt;br /&gt;
Der SCL- und der SDA-Pin stellen die Schnittstelle des einzelnen MC mit dem Bus dar. Zusätzlich ist intern vorgesehen, dass Spannungsspitzen, welche kürzer als 50ns sind, herausgefiltert werden. Es besteht bei manchen Konfigurationen die Möglichkeit, die internen Pull-Up Widerstände zu verwenden, dies kann die Verwendung der externen überflüssig machen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich verfügt der ATmega über einen Bitraten-Generator, welcher im Masterbetrieb das entsprechende Signal auf SCL gibt. Die Taktrate wird durch das TWBR (TWI Bit Rate Register) und TWSR (TWI Status Register) festgelegt. Zu beachten ist, dass die interne Taktfrequenz der einzelnen Slaves mindestens 16 mal höher als die Taktrate des Bus ist. Diese ergibt sich nach folgender Formel:&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/mc-project/Pages/AVR/TWI/twi_formel.gif&lt;br /&gt;
&lt;br /&gt;
* TWBR - TWI Bit Rate Register&lt;br /&gt;
* TWPS - TWI Prescaler Bits im TWI Status Register&lt;br /&gt;
&lt;br /&gt;
Des weiteren verfügt der MC über je ein Daten- und Adressschieberegister, einen START/STOP Controller und die Arbitrierungslogik. Das TWDR (TWI Data Register) beinhaltet entweder die Adresse und Daten welche gesendet werden sollen oder die empfangene Adresse samt Daten. Zusätzlich existiert noch ein Register, welches das (N)ACK-Bit enthält, das aber nicht direkt zugänglich ist. Jedoch kann es im Empfangsmodus durch verändern von TWCR (TWI Control Register) bzw. im Empfangsmodus durch verändern von TWSR manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Der START/STOP Controller ist wie sein Name bereits sagt, dafür verantwortlich, den anderen Teilnehmern am Bus mitzuteilen, dass der entsprechende Master eine Übertragung plant bzw. beendet. Zusätzlich führt er auch den bereits erwähnten REPEATED START durch. Eine Besonderheit ist, dass er solche START/STOP-Zeichen auf dem Bus sogar detektieren kann, wenn sich der Controller in einem der Sleep-Modi befindet. Er kann somit &amp;quot;aufgeweckt&amp;quot; werden, wenn er von einem Master adressiert wird.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer Bestandteil des TWI ist die &amp;quot;Adress Match Unit&amp;quot;. Diese überwacht, ob die empfangenen Adress-Bytes mit denen im TWAR (TWI Adress Register) übereinstimmen. Wenn TWGCE (TWI General Call Recognition Enable) in TWAR gesetzt ist, werden alle eingehenden Adress-Bytes zusätzlich noch daraufhin überprüft, ob eine allgemeine Ruf (0000 000) vorliegt. Sollte eine Übereinstimmung vorliegen, wird die Kontrolleinheit informiert, eventuelle Korrekturmaßnahmen können durchgeführt werden. Die TWI-Logik kann nun die Anforderung bestätigen, je nach dem welche Einstellungen in TWCR getroffen wurden. Wie bereits oben angesprochen wurde, arbeitet die Adress-Vergleichs-Logik sogar, wenn sich der MC in einem der Sleep-Modi befindet. Man kann den MC somit per TWI reaktivieren. Einzige Ausnahme bildet der Fall, dass der Controller zuvor durch einen anderen Interrupt reaktiviert wurde. Danach geht die TWI-Logik sofort in den Leerlauf. Sollte das bei der vorgesehenen Problemstellung zu Problemen führen, bleibt nur der Ausweg sämtliche anderen Interrupts in der Hinsicht zu sperren, dass sie den Controller nicht mehr reaktivieren können.&lt;br /&gt;
&lt;br /&gt;
Die Kontrolleinheit des TWI beobachtet ständig den Bus und antwortet auf Anfragen entsprechend den Einstellungen in TWCR. Tritt ein Ereignis ein, auf welches die angesprochene Einheit reagieren soll, so wird automatisch TWINT (TWI Interrupt Flag) gesetzt. Im nächsten Taktzyklus wird dann TWSR aktualisiert, in ihm steht jetzt ein Code mit welchem das Ereignis spezifiziert werden kann. TWSR beinhaltet nur relevante Informationen, wenn TWINT gesetzt wird, andernfalls beinhaltet es bloß einen Statuscode, welcher aussagt, dass keine relevanten Informationen vorliegen. Solange TWINT gesetzt ist, wird SCL auf Low Pegel belassen. Dies gibt dem angesprochenen MC die Chance, alle Anwendungen erst zu beenden, bevor er sich der Transmission widmet. TWINT wird gesetzt wenn:&lt;br /&gt;
&lt;br /&gt;
* wenn das TWI START/REPEATED START gesendet hat&lt;br /&gt;
* wenn das TWI SLA +R/W gesendet hat&lt;br /&gt;
* wenn das TWI ein Adress-Byte gesendet hat&lt;br /&gt;
* wenn das TWI seine &amp;quot;Vormacht&amp;quot; auf dem Bus verloren hat&lt;br /&gt;
* wenn das TWI durch seine eigene Slave-Adresse bzw. einen allgemeinen Ruf (general call) adressiert wurde&lt;br /&gt;
* wenn das TWI ein Datenbyte empfangen hat&lt;br /&gt;
* wenn ein STOP oder REPEATED START empfangen wurde, während es immer noch als Slave angesprochen ist&lt;br /&gt;
* wenn ein Busfehler durch einen illegalen START bzw. STOP aufgetreten ist&lt;br /&gt;
&lt;br /&gt;
== Benutzung des TWI ==&lt;br /&gt;
&lt;br /&gt;
Das TWI ist wie bereits ausführlich dargestellt wurde, byte- bzw. interruptbasiert. Dadurch ist es der Anwendersoftware möglich, parallel zum Datenversand bzw. -empfang auf dem TWI Bus noch weitere Anwendungen (Operationen) auszuführen. Die Ausführung einer ISR ist allein durch das Setzen von TWIE (TWI Interrupt Enable) in TWCR bedingt (die Interrupts müssen natürlich auch global freigegeben sein). Es ist Sache des Anwenders, ob das Setzen von TWINT einen Interrupt verursachen soll. Ist TWIE nicht gesetzt, so ist es dem Programm selbst überlassen, ständig TWINT zu prüfen, um sämtliche Ereignisse auf dem Bus mit zu bekommen. &lt;br /&gt;
&lt;br /&gt;
Bei jedem Setzen von TWINT ist eine Operation auf dem Bus abgeschlossen worden und es wird eine Antwort erwartet. In diesem Fall beinhaltet TWSR einen Wert, welcher ein direktes Maß für den aktuellen Status des Bus ist. Die Software legt nun fest, welche Aktion mit dem nächsten Buszyklus durchgeführt werden soll, indem sie TWCR und TWDR entsprechend verändert. Im folgenden wird schrittweise ein Beispiel für den Ablauf einer Übertragung gegeben.&lt;br /&gt;
&lt;br /&gt;
Zuerst muss vom Master ein START-Signal auf den Bus gegeben werden. Dies erfolgt durch Schreiben eines speziellen Wertes in TWCR. Nach Abschluss der Operation wird TWINT gesetzt. Die Logik wartet nun so lange, bis durch den Anwender das Flag wieder gelöscht wurde (durch Schreiben einer &#039;1&#039;). Unmittelbar nach dem Löschen von TWINT beginnt die Logik damit das START-Signal zu senden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);                        //TWSTA = TWI START Condition Bit&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem Senden des START wird sofort wieder TWINT in TWCR gesetzt. Zusätzlich beinhaltet TWSR jetzt den entsprechenden Status Code, welcher mitteilt, dass START erfolgreich gesendet wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while  (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nachdem durch die Applikation TWSR daraufhin überprüft wurde, dass START erfolgreich gesendet wurde, kann es nun weitergehen. Im Fehlerfall könnte beispielsweise eine vom Anwender definierte Fehlerroutine greifen. &lt;br /&gt;
&lt;br /&gt;
Nun muss SLA_W in TWDR geladen werden. Ist dies abgeschlossen, muss wiederum ein spezieller Wert in TWCR geschrieben werden, um der TWI-Logik mitzuteilen, dass die Adresse und der Schreibbefehl aus TWDR gesendet werden können. Unmittelbar nachdem durch den Anwender dann TWINT in TWCR gelöscht wurde (Schreiben einer &#039;1&#039;) sendet das TWI das Adresspaket.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != START)&lt;br /&gt;
  ERROR();                                                                //Fehlerbehandlung&lt;br /&gt;
TWDR = SLA_W;&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT) | (1&amp;lt;&amp;lt;TWEN);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach Abschluss der Sendung wird wiederum TWINT gesetzt in TWSR steht der entsprechende Statuscode, welcher über Erfolg bzw. Misserfolg der Sendung urteilt. In ihm ist auch das ACK-Bit des angesprochenen Slaves enthalten (oder auch nicht, was dann einen Fehler bedeuten würde).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nach der Prüfung von TWSR ob bei der Sendung keine Fehler aufgetreten sind, kann das Datenpaket in TWDR geladen werden. Erneut muss ein spezieller Wert in TWCR geschrieben werden, welcher der Logik sagt, dass ein Datenpaket aus TWDR versendet werden soll. Nach dem Löschen von TWINT wird dieses automatisch versendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != MT_SLA_ACK)&lt;br /&gt;
  ERROR();&lt;br /&gt;
TWDR = DATA;&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT) | (1&amp;lt;&amp;lt;TWEN);&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nachdem TWINT gesetzt wurde kann mit Hilfe von TWSR überprüft werden, ob das Datenpaket erfolgreich gesendet und vom angesprochenen Slave angenommen wurde (ACK-Bit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
 &amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachdem bis hierhin alles funktioniert hat (angenommen), muss nun nur noch ein STOP gesendet werden. Dies erfolgt analog zu den obigen Ausführungen durch Schreiben eines speziellen Wertes in TWCR. Nach dem Löschen von TWINT wird dieses gesendet. Allerdings wird danach TWINT nicht automatisch wieder gesetzt, wie es zuvor immer der Fall war.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != MT_DATA_ACK)&lt;br /&gt;
  ERROR();&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEN)|&lt;br /&gt;
(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkung: Selbstverständlich muss zuvor beim anzusprechenden Slave in TWAR (TWI Adress Register) eine Adresse festgelegt werden, damit er auch gezielt angesprochen werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
== Übertragungsmodi ==&lt;br /&gt;
&lt;br /&gt;
Das TWI kann prinzipiell in vier verschiedenen Modi arbeiten: Master Transmitter (MT), Master Receiver (MR), Slave Transmitter (ST), Slave Receiver (SR). Diese können natürlich alle in einer Anwendung verwendet werden, je nachdem, wie sie es erfordert.&lt;br /&gt;
&lt;br /&gt;
=== Master Transmitter Mode ===&lt;br /&gt;
&lt;br /&gt;
Im MTM wird eine Abfolge von Bytes (Daten) an einen SR gesendet. Um ihn zu benutzen, muss das Adresspaket nach dem gesendeten START eine bestimmte Form aufweisen. Wird SLA+W gesendet, liegt der MTM vor, für SLA+R wäre es der MRM.&lt;br /&gt;
Das Senden eines START gestaltet sich wie folgt (TWCR):&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* TWEN:    Aktivierung des TWI&lt;br /&gt;
* TWSTA:    Senden des START&lt;br /&gt;
* TWINT:    um TWINT zu löschen&lt;br /&gt;
&lt;br /&gt;
Das TWI wartet nun solange, bis der Bus frei ist und sendet dann START. Danach wird TWINT wieder gesetzt und TWSR aktualisiert. Es sollte jetzt 0x08 enthalten. Beim Auslesen des Status-Code müssen die Prescaler-Bits mit Null maskiert werden. Um den MTM zu benutzen, muss SLA+W in TWDR geschrieben werden. Nachdem TWINT gelöscht wurde, wird dies gesendet. TWCR muss dazu die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nachdem SLA+W gesendet und das ACK-Bit empfangen wurde, wird TWINT erneut gesetzt. Der Statuscode in TWSR kann nun unter anderem folgende Formen haben: 0x18, 0x20, 0x38. &lt;br /&gt;
&lt;br /&gt;
Nachdem bis hierhin alles erfolgreich funktioniert hat, kann jetzt ein Datenpaket versendet werden. Dies erfolgt durch Schreiben der Daten in TWDR. TWDR kann nur aktualisiert werden, wenn TWINT gesetzt ist, andernfalls kommt es zu einem Fehler, TWWC (TWI Write Collision Bit) wird gesetzt. Um die Daten zu senden, muss TWINT erneut gelöscht werden. TWCR sollte so aussehen:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Dieses Schema wiederholt sich nun solange, bis alle Daten versendet wurden und ein STOP gesendet werden kann. Dies erfolgt folgendermaßen:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |1    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Ein erneuter Start (REPEATED START) erfolgt durch Schreiben der folgenden Werte in TWCR:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach einem REPEATED START kann der Master denselben Slave erneut kontaktieren oder auch einen anderen, ohne ein STOP zu senden. Der REPEATED START erlaubt dem Master das Wechseln zwischen Slaves, MTM und MRM ohne die Kontrolle über den Bus zu verlieren.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.176 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Master Receiver Mode ===&lt;br /&gt;
&lt;br /&gt;
Im MRM empfängt der Master Daten von einem ST. Zunächst muss wieder START gesendet werden. Das folgende Adresspaket sollte dann SLA+R enthalten.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* TWEN:    Aktivierung des TWI&lt;br /&gt;
* TWSTA:    Senden des START&lt;br /&gt;
* TWINT:    um TWINT zu löschen&lt;br /&gt;
&lt;br /&gt;
Das TWI wartet nun solange, bis der Bus frei ist und sendet dann START. Danach wird TWINT wieder gesetzt und TWSR aktualisiert. Es sollte jetzt 0x08 enthalten. Beim Auslesen des Status-Code müssen die Prescaler-Bits mit Null maskiert werden. Um den MTM zu benutzen, muss SLA+R in TWDR geschrieben werden. Nachdem TWINT gelöscht wurde, wird dies gesendet. TWCR muss dazu die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nachdem SLA+R gesendet und das ACK-Bit empfangen wurde, wird TWINT erneut gesetzt. Der Statuscode in TWSR kann nun unter anderem folgende Formen haben: 0x38, 0x40, 0x48. &lt;br /&gt;
Die empfangenen Daten können aus TWDR gelesen werden, so denn TWINT gesetzt ist. Dieses Schema kann sich bis zum Empfang des letzten Bytes immer wieder wiederholen. Nachdem das letzte Byte empfangen wurde, kann der Master dem Slave durch senden von NACK klar machen, dass keine Daten mehr erwartet werden. Beendet wird der Transfer durch senden von STOP oder REPEATED START.&lt;br /&gt;
Für STOP muss folgendes in TWCR geschrieben werden:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |1    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Für einen REPEATED START muss folgendes in TWCR geschrieben werden:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach einem REPEATED START kann der Master denselben Slave erneut kontaktieren oder auch einen anderen, ohne ein STOP zu senden. Der REPEATED START erlaubt dem Master das Wechseln zwischen Slaves, MTM und MRM ohne die Kontrolle über den Bus zu verlieren.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.179 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Slave Receiver Mode ===&lt;br /&gt;
&lt;br /&gt;
Im SRM werden Daten vom MT empfangen. Um einen Atmega8 im SRM zu betreiben, müssen TWAR und TWCR die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
TWAR:&lt;br /&gt;
Die oberen 7 Bit stellen die Adress dar, an die das TWI antwortet, wenn es von einem Master angesprochen wird. Wenn das LSB (Least Significant Bit) in Form von TWGCE gesetzt ist, antwortet der Slave auch auf allgemeine Rufe (general calls), andernfalls natürlich nicht.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWA6|TWA5|TWA4|TWA3|TWA2|TWA1|TWA0|TWGCE&lt;br /&gt;
 |Hier|steht|dann|die|Adresse|des|Slave!|X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
TWCR:&lt;br /&gt;
TWEN muss zum aktivieren des TWI gesetzt werden. TWEA muss gesetzt werden, damit der Slave antwortet, falls er von einem Master oder gegeben falls durch einen general call angesprochen wird. TWSTA und TWSTO müssen auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |0    |1   |0    |0    |0   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Wenn TWAR und TWCR initialisiert wurden, wartet der Slave ab, bis er mit seiner Adresse bzw. gegebenen falls durch einen generall call angesprochen wird gefolgt von einem Datenrichtungs-Bit. Hierbei steht eine &#039;0&#039; für Schreiben (SR) und eine &#039;1&#039; für Lesen (ST).&lt;br /&gt;
Nachdem die Logik ihre eigene Adresse und ein Schreib-Bit erhalten hat, wird TWINT gesetzt und TWSR beinhaltet den entsprechenden Statuscode. Mit seiner Hilfe kann die Software dann eine sinnvolle Reaktion einleiten. Der Eintritt in den SRM kann auch erfolgen, wenn ein Master sein Vorrecht auf dem Bus verloren hat (0x68, 0x78).&lt;br /&gt;
&lt;br /&gt;
Wenn TWEA während eines Transfers zurückgesetzt wird, wird das TWI ein NACK (Not Acknowledge) auf den Bus nach Empfang des nächsten Bytes geben. Dies kann verwendet werden, wenn der Slave nicht mehr in der Lage ist, mehr Bytes zu empfangen. Solange TWEA &#039;0&#039; ist, reagiert das TWI nicht mehr auf seine eigene Slave-Adresse. Jedoch wird der Bus weiterhin beobachtet und das TWI ist nach dem Setzen von TWEA sofort wieder einsatzbereit. Somit kann dieses Feature verwendet werden, um einen Baustein für eine bestimmte Zeitspanne vom Bus zu nehmen.&lt;br /&gt;
&lt;br /&gt;
In sämtlichen Sleep-Modi (außer Idle Mode) ist der Systemtakt des TWI inaktiv. Dessen zu trotz kann das TWI durch setzen von TWEA allein mit Hilfe des Bustaktes erfassen, wenn es mit seiner Adresse bzw. durch einen general call angesprochen wird. Somit kann das TWI den Controller aufwecken. Während der Aufweck-Phase kann SCL auf L-Pegel gehalten werden wenn TWINT gelöscht ist (Schreiben einer &#039;1&#039;). Der Datenempfang kann wieder im Normalbetrieb stattfinden. Zu beachten ist, dass solange SCL auf L-Pegel ist keine anderen Transmissionen stattfinden können. Wichtig ist, dass TWDR nach dem Aufwecken nicht mehr das letzte Byte, welches auf dem Bus war, enthält.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.182 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Slave Transmitter Mode ===&lt;br /&gt;
&lt;br /&gt;
Im STM werden Daten an einen MR gesendet. Um den Controller im STM zu betreiben, müssen TWAR und TWCR wie folgt initialisiert werden.&lt;br /&gt;
&lt;br /&gt;
TWAR:&lt;br /&gt;
Die oberen 7 Bit stellen die Adress dar, an die das TWI antwortet, wenn es von einem Master angesprochen wird. Wenn das LSB (Least Significant Bit) in Form von TWGCE gesetzt ist, antwortet der Slave auch auf allgemeine Rufe (general calls), andernfalls natürlich nicht.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWA6|TWA5|TWA4|TWA3|TWA2|TWA1|TWA0|TWGCE&lt;br /&gt;
 |Hier|steht|dann|die|Adresse|des|Slave!|X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
TWCR:&lt;br /&gt;
TWEN muss zum aktivieren des TWI gesetzt werden. TWEA muss gesetzt werden, damit der Slave antwortet, falls er von einem Master oder gegeben falls durch einen general call angesprochen wird. TWSTA und TWSTO müssen auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |0    |1   |0    |0    |0   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach der Initialisierung wartet das TWI auf eine Anfrage gefolgt von einem Datenrichtungsbit. Wird das TWI angesprochen wird TWINT gesetzt und TWSR beinhaltet den Statuscode. Mit seiner Hilfe kann das weitere Vorgehen festgelegt werden. Ein Controller kann auch in den STM gelangen, wenn er die Hoheit auf dem Bus an einen anderen Master verliert (0xB0). &lt;br /&gt;
&lt;br /&gt;
Wird TWEA während eines Transfers gesetzt, wird das aktuelle Byte noch fertig gesendet und Status 0xC0 oder 0xC8 tritt ein, je nachdem ob der Master ACK oder NACK nach dem letzten Byte gesendet hatte. Das TWI wird in einen Blockierzustand gehen, unabhängig davon, ob der Master den Transfer fortsetzt. So erhält der Master nur noch &#039;1&#039; auf dem seriellen Bus. Status 0xC8 tritt ein, wenn der Master weitere Daten fordert (durch Senden von ACK), obwohl der Slave bereits das letzte Byte gesendet hat (TWEA &#039;0&#039; und erwartet NACK).&lt;br /&gt;
&lt;br /&gt;
Trotz des Blockierzustandes wird der Bus weiter beobachtet und das TWI kann durch setzen von TWEA jederzeit wieder daran teilnehmen. Somit kann der Slave mit Hilfe von TWEA kurzzeitig vom Bus isoliert werden.&lt;br /&gt;
&lt;br /&gt;
In sämtlichen Sleep-Modi (außer Idle Mode) ist der Systemtakt des TWI inaktiv. Dessen zu trotz kann das TWI durch setzen von TWEA allein mit Hilfe des Bustaktes erfassen, wenn es mit seiner Adresse bzw. durch einen general call angesprochen wird. Somit kann das TWI den Controller aufwecken. Während der Aufweck-Phase kann SCL auf L-Pegel gehalten werden wenn TWINT gelöscht ist (Schreiben einer &#039;1&#039;). Der Datenversand kann wieder im Normalbetrieb stattfinden. Zu beachten ist, dass solange SCL auf L-Pegel ist keine anderen Transmissionen stattfinden können. Wichtig ist, dass TWDR nach dem Aufwecken nicht mehr das letzte Byte, welches auf dem Bus war, enthält.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.185 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den Betriebsart bezogenen Statuscodes gibt es noch zwei, welche davon unabhängig sind.&lt;br /&gt;
Status 0xF8 bedeutet, dass keine relevanten Informationen vorhanden sind, da TWINT nicht gesetzt ist. Dieser Fall tritt bei einem Statuswechsel ein oder wenn TWI im Moment nicht am Bus beteiligt ist.&lt;br /&gt;
&lt;br /&gt;
Status 0x00 steht für einen Busfehler während einer Übertragung. Ursache kann das Senden von START oder STOP zu einem nicht zulässigem Zeitpunkt sein. Bei solch einem Fehler wird TWINT automatisch gesetzt. Um die Fehlerroutine zu verlassen, muss TWSTO gesetzt und TWINT gelöscht werden. Dieses führt dazu, dass das TWI in den nicht adressierten Slave-Modus geht und SDA und SCL wieder freigegeben werden. Es wird kein STOP gesendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Wem das alles zuviel Theorie war und wer das I2C-Interface einmal im Einsatz erleben möchte, dem lege ich die Rubrik ICs &amp;amp; Co ans Herz. Dort wird die Verwendung eines I2C-EEPROMS demonstriert.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken ===&lt;br /&gt;
* [http://www.jtronics.de/elektronik-avr/lib-i2ctwi-avr.html AVR TWI Slave]&lt;br /&gt;
* [http://jump.to/fleury Peter Fleury&#039;s AVR I2C Library]&lt;br /&gt;
&lt;br /&gt;
===I²C-Bausteine===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR]] &lt;br /&gt;
[[Category:Mc-project.de]]&lt;br /&gt;
[[Category:I2C]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_TWI&amp;diff=49670</id>
		<title>AVR TWI</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_TWI&amp;diff=49670"/>
		<updated>2010-08-03T13:34:20Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Grundlagen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von Alexander Starke&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Das TWI (Two Wire Interface) ist begründet durch seinen Aufbau ideal auf typische Mikrocontroller Applikationen zugeschnitten. Durch seinen 7 Bit breiten Adressraum können bis zu 128 (2&amp;lt;sup&amp;gt;7&amp;lt;/sup&amp;gt; = 128) Geräte miteinander verschaltet werden. Im Gegensatz zum SPI ([[Serial Peripheral Interface]]) werden nur zwei Busleitungen benötigt. Eine dient der Bereitstellung des Taktes (SCL) und die andere dem Datentransport (SDA). Die einzige zusätzlich benötigt Hardware besteht aus zwei Pull-Up Widerständen, welche von jeweils einer Busleitung gegen Vcc (5V) geschalten werden. Da alle Bustreiber mit offenem Kollektor bzw. Drain am Bus anliegen, ergibt sich eine logische UND-Verknüpfung. D.h., sobald irgendein Gerät auf einer der Busleitungen Low-Pegel anlegt, liegt automatisch die gesamte Busleitung auf Low. Der BUS hat nur High-Pegel, wenn alle angeschlossenen Geräte auch High-Pegel an ihrer entsprechenden Schnittstelle haben.&lt;br /&gt;
&lt;br /&gt;
Genau wie beim SPI initiiert auch beim TWI der Master den Datentransfer und beendet selbigen auch wieder. Gestartet wird eine Transmission durch eine Start-Bedingung und entsprechend beendet durch eine Stop-Bedingung. Während einer Transmission gilt der Bus als &amp;quot;busy&amp;quot; (beschäftigt) und kein anderer Master darf versuchen, Kontrolle über ihn zu erlangen. Einzige Ausnahme bildet hier der Fall, dass vor einer Stop-Bedingung durch den gerade aktiven Master noch eine zusätzliche Start-Bedingung auf den Bus gegeben wird. Dieser Fall tritt normalerweise dann ein, wenn der Master noch weitere Daten zu versenden hat und nicht die Kontrolle über den Bus verlieren möchte. Nach solch einem wiederholten Start (Repeated Start) ist der Bus wieder beschäftigt, bis zum nächsten Stop.&lt;br /&gt;
Start- und Stop-Bedingungen werden signalisiert, indem der Pegel der SDA-Leitung wechselt, während SCL High-Pegel hat.&lt;br /&gt;
&lt;br /&gt;
Alle Adresspakete auf dem TWI Bus haben eine Länge von 8 Bit. Davon beinhalten 7 Bit wie bereits eingangs erwähnt die Adresse der angesprochenen Komponente. Zusätzlich gibt es noch ein Bit, dass darüber bestimmt, ob ein Lese- oder ein Schreibzugriff durchgeführt werden soll (R/W=1 -&amp;gt; Lesen; RW=0 -&amp;gt; Schreiben). Das 9 Bit dient der Bestätigung. Wenn ein Slave bemerkt, dass er angesprochen wird, so bestätigt er dies, indem er mit dem 9. Taktzyklus (ACK) von SCL SDA auf Low-Pegel legt. Sollte der angesprochene Slave aus irgendwelchen Gründen nicht antworten können, so sollte SDA auf H-Pegel bleiben. Der Master hat dann die Wahl, ob er ein Stop sendet oder einen wiederholten Start durchführt.&lt;br /&gt;
&lt;br /&gt;
* SLA +R   --&amp;gt;    Adresspaket mit einer Slave-Adresse und einem Lese-Bit&lt;br /&gt;
* SLA +W  --&amp;gt;    Adresspaket mit einer Slave-Adresse und einem Schreib-Bit&lt;br /&gt;
&lt;br /&gt;
Das höchstwertige Bit wird prinzipiell zuerst übertragen (MSB Most Significant Bit). Die Slave-Adressen können durch den Anwender frei gewählt werden, nur 0000 000 ist reserviert, hiermit werden alle Slaves angesprochen. Wird ein solcher Zugriff durchgeführt, so sollten alle Slaves im ACK-Zyklus SDA auf L-Pegel legen.&lt;br /&gt;
Benutzt wird diese Aktion, wenn der Master die selben Daten an mehrere Slaves senden möchte. Sinn macht die Verwendung nur in Verbindung mit dem Schreib-Bit. Ein Setzen des Lese-Bits hätte zur Folge, dass verschiedene Slaves ja verschiedene Daten auf den Bus stellen könnten, was zu einem Durcheinander führen würde. Wird das Schreib-Bit gesetzt, so setzen im ACK-Zyklus alle Slaves SDA auf L-Pegel, welche den allgemeinen Adressaufruf erhalten und ausgewertet haben (also die nicht beschäftigt waren). Die folgenden Datenpakete werden dann von allen Slaves empfangen, welche SDA auf L-Pegel gelegt hatten.&lt;br /&gt;
&lt;br /&gt;
Alle Datenpakete auf dem TWI-Bus haben analog zu den Adresspaketen 9 Bit. Hiervon sind 8 Datenbits. Das 9. dient der Bestätigung. Während einer Datenübertragung ist es Aufgabe des Masters, den Takt, das Start- und das Stopzeichen bereitzustellen. Aufgabe des Empfängers ist die Bestätigung der erhaltenen Daten, indem er die SDA-Leitung während des 9. SCL-Zyklus auf L-Pegel legt. Dieses wird als ACK bezeichnet (Acknowledge). Bleibt SDA auf H-Pegel, so wird dem Sender signalisiert, dass die gesendeten Daten nicht empfangen wurden (NACK). Das MSB wird zuerst übertragen.&lt;br /&gt;
&lt;br /&gt;
Wenn man nun Adress- und Datenpakete kombiniert, hat man schon eine fertige Transmission. Diese besteht aus:&lt;br /&gt;
&lt;br /&gt;
* START    --&amp;gt;    SLA R/W    --&amp;gt;    ein oder mehr Datenpakete    --&amp;gt;    STOP&lt;br /&gt;
&lt;br /&gt;
Ein START gefolgt von einem STOP ist nicht zulässig. Wenn der Takt des Masters für den Slave zu schnell ist oder er noch mehr Zeit zur Bearbeitung braucht, so kann er SCL einfach länger auf L-Pegel halten. Die Verlängerung der L-Phase von SCL hat allerdings keinen Einfluss auf die Länge der H-Phase, da diese vom Master zur Verfügung gestellt wird. Dadurch kann es allerdings zu einer Reduzierung des Datentransfers kommen.&lt;br /&gt;
&lt;br /&gt;
== Multi-Master-Bussysteme ==&lt;br /&gt;
&lt;br /&gt;
Das TWI-Bussystem erlaubt den Multi-Master Betrieb. Es wurden spezielle Vorkehrungen getroffen, so dass auch wenn mehrere Master zur selben Zeit eine Transmission beginnen wollen keine Probleme auftreten und der Bus normal funktioniert. Nur die zwei folgenden Probleme sollten beachtet werden:&lt;br /&gt;
&lt;br /&gt;
# Es ist Sache des Anwenders, seine Algorithmen so auszulegen, dass in diesem Fall nur ein Master seine Transmission fortsetzt. Alle anderen Master sollten ihre Transmission sofort abbrechen. Diesen Auswahlprozess zwischen den Mastern nennt man Arbitrierung (Entscheidung). Wenn ein Master bemerkt, dass er den Entscheidungsprozess (die Arbitrierung) verloren hat, sollte er sofort in den Slave-Modus gehen, da es sein kann, dass der Master welcher den Prozess gewonnen hat ihn adressieren will. Die Tatsache, dass mehrere Master versucht hatten, eine Übertragung zu starten, sollte für die Slaves nicht feststellbar sein, die Daten auf dem Bus dürfen nicht beschädigt sein.&lt;br /&gt;
# Da verschiedene Master mit verschiedenen Taktfrequenzen auf dem Bus arbeiten könnten, ist eine Festlegung zu treffen, wie man diese synchronisiert. Dieses erleichtert auch den Arbitrierungsprozess.&lt;br /&gt;
&lt;br /&gt;
Diese Lösung dieses Problems stellt die schon oben angesprochene UND-Verknüpfung aller Komponenten auf dem Bus dar. So werden alle seriellen Taktraten der einzelnen Master UND verknüpft. Somit ergibt sich ein High-Pegel entsprechend dem des Masters mit dem kürzesten H-Pegel, der Low-Pegel ist durch den Master mit der geringsten Taktrate gegeben.&lt;br /&gt;
&lt;br /&gt;
Da der Multi-Master Betrieb für meine Anwendung keinen Belang hat, werde ich hier nicht näher darauf eingehen.&lt;br /&gt;
&lt;br /&gt;
==Aufbau des TWI==&lt;br /&gt;
&lt;br /&gt;
Der SCL- und der SDA-Pin stellen die Schnittstelle des einzelnen MC mit dem Bus dar. Zusätzlich ist intern vorgesehen, dass Spannungsspitzen, welche kürzer als 50ns sind, herausgefiltert werden. Es besteht bei manchen Konfigurationen die Möglichkeit, die internen Pull-Up Widerstände zu verwenden, dies kann die Verwendung der externen überflüssig machen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich verfügt der ATmega über einen Bitraten-Generator, welcher im Masterbetrieb das entsprechende Signal auf SCL gibt. Die Taktrate wird durch das TWBR (TWI Bit Rate Register) und TWSR (TWI Status Register) festgelegt. Zu beachten ist, dass die interne Taktfrequenz der einzelnen Slaves mindestens 16 mal höher als die Taktrate des Bus ist. Diese ergibt sich nach folgender Formel:&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/mc-project/Pages/AVR/TWI/twi_formel.gif&lt;br /&gt;
&lt;br /&gt;
* TWBR - TWI Bit Rate Register&lt;br /&gt;
* TWPS - TWI Prescaler Bits im TWI Status Register&lt;br /&gt;
&lt;br /&gt;
Des weiteren verfügt der MC über je ein Daten- und Adressschieberegister, einen START/STOP Controller und die Arbitrierungslogik. Das TWDR (TWI Data Register) beinhaltet entweder die Adresse und Daten welche gesendet werden sollen oder die empfangene Adresse samt Daten. Zusätzlich existiert noch ein Register, welches das (N)ACK-Bit enthält, das aber nicht direkt zugänglich ist. Jedoch kann es im Empfangsmodus durch verändern von TWCR (TWI Control Register) bzw. im Empfangsmodus durch verändern von TWSR manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Der START/STOP Controller ist wie sein Name bereits sagt, dafür verantwortlich, den anderen Teilnehmern am Bus mitzuteilen, dass der entsprechende Master eine Übertragung plant bzw. beendet. Zusätzlich führt er auch den bereits erwähnten REPEATED START durch. Eine Besonderheit ist, dass er solche START/STOP-Zeichen auf dem Bus sogar detektieren kann, wenn sich der Controller in einem der Sleep-Modi befindet. Er kann somit &amp;quot;aufgeweckt&amp;quot; werden, wenn er von einem Master adressiert wird.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer Bestandteil des TWI ist die &amp;quot;Adress Match Unit&amp;quot;. Diese überwacht, ob die empfangenen Adress-Bytes mit denen im TWAR (TWI Adress Register) übereinstimmen. Wenn TWGCE (TWI General Call Recognition Enable) in TWAR gesetzt ist, werden alle eingehenden Adress-Bytes zusätzlich noch daraufhin überprüft, ob eine allgemeine Ruf (0000 000) vorliegt. Sollte eine Übereinstimmung vorliegen, wird die Kontrolleinheit informiert, eventuelle Korrekturmaßnahmen können durchgeführt werden. Die TWI-Logik kann nun die Anforderung bestätigen, je nach dem welche Einstellungen in TWCR getroffen wurden. Wie bereits oben angesprochen wurde, arbeitet die Adress-Vergleichs-Logik sogar, wenn sich der MC in einem der Sleep-Modi befindet. Man kann den MC somit per TWI reaktivieren. Einzige Ausnahme bildet der Fall, dass der Controller zuvor durch einen anderen Interrupt reaktiviert wurde. Danach geht die TWI-Logik sofort in den Leerlauf. Sollte das bei der vorgesehenen Problemstellung zu Problemen führen, bleibt nur der Ausweg sämtliche anderen Interrupts in der Hinsicht zu sperren, dass sie den Controller nicht mehr reaktivieren können.&lt;br /&gt;
&lt;br /&gt;
Die Kontrolleinheit des TWI beobachtet ständig den Bus und antwortet auf Anfragen entsprechend den Einstellungen in TWCR. Tritt ein Ereignis ein, auf welches die angesprochene Einheit reagieren soll, so wird automatisch TWINT (TWI Interrupt Flag) gesetzt. Im nächsten Taktzyklus wird dann TWSR aktualisiert, in ihm steht jetzt ein Code mit welchem das Ereignis spezifiziert werden kann. TWSR beinhaltet nur relevante Informationen, wenn TWINT gesetzt wird, andernfalls beinhaltet es bloß einen Statuscode, welcher aussagt, dass keine relevanten Informationen vorliegen. Solange TWINT gesetzt ist, wird SCL auf Low Pegel belassen. Dies gibt dem angesprochenen MC die Chance, alle Anwendungen erst zu beenden, bevor er sich der Transmission widmet. TWINT wird gesetzt wenn:&lt;br /&gt;
&lt;br /&gt;
* wenn das TWI START/REPEATED START gesendet hat&lt;br /&gt;
* wenn das TWI SLA +R/W gesendet hat&lt;br /&gt;
* wenn das TWI ein Adress-Byte gesendet hat&lt;br /&gt;
* wenn das TWI seine &amp;quot;Vormacht&amp;quot; auf dem Bus verloren hat&lt;br /&gt;
* wenn das TWI durch seine eigene Slave-Adresse bzw. einen allgemeinen Ruf (general call) adressiert wurde&lt;br /&gt;
* wenn das TWI ein Datenbyte empfangen hat&lt;br /&gt;
* wenn ein STOP oder REPEATED START empfangen wurde, während es immer noch als Slave angesprochen ist&lt;br /&gt;
* wenn ein Busfehler durch einen illegalen START bzw. STOP aufgetreten ist&lt;br /&gt;
&lt;br /&gt;
== Benutzung des TWI ==&lt;br /&gt;
&lt;br /&gt;
Das TWI ist wie bereits ausführlich dargestellt wurde, byte- bzw. interruptbasiert. Dadurch ist es der Anwendersoftware möglich, parallel zum Datenversand bzw. -empfang auf dem TWI Bus noch weitere Anwendungen (Operationen) auszuführen. Die Ausführung einer ISR ist allein durch das Setzen von TWIE (TWI Interrupt Enable) in TWCR bedingt (die Interrupts müssen natürlich auch global freigegeben sein). Es ist Sache des Anwenders, ob das Setzen von TWINT einen Interrupt verursachen soll. Ist TWIE nicht gesetzt, so ist es dem Programm selbst überlassen, ständig TWINT zu prüfen, um sämtliche Ereignisse auf dem Bus mit zu bekommen. &lt;br /&gt;
&lt;br /&gt;
Bei jedem Setzen von TWINT ist eine Operation auf dem Bus abgeschlossen worden und es wird eine Antwort erwartet. In diesem Fall beinhaltet TWSR einen Wert, welcher ein direktes Maß für den aktuellen Status des Bus ist. Die Software legt nun fest, welche Aktion mit dem nächsten Buszyklus durchgeführt werden soll, indem sie TWCR und TWDR entsprechend verändert. Im folgenden wird schrittweise ein Beispiel für den Ablauf einer Übertragung gegeben.&lt;br /&gt;
&lt;br /&gt;
Zuerst muss vom Master ein START-Signal auf den Bus gegeben werden. Dies erfolgt durch Schreiben eines speziellen Wertes in TWCR. Nach Abschluss der Operation wird TWINT gesetzt. Die Logik wartet nun so lange, bis durch den Anwender das Flag wieder gelöscht wurde (durch Schreiben einer &#039;1&#039;). Unmittelbar nach dem Löschen von TWINT beginnt die Logik damit das START-Signal zu senden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);                        //TWSTA = TWI START Condition Bit&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem Senden des START wird sofort wieder TWINT in TWCR gesetzt. Zusätzlich beinhaltet TWSR jetzt den entsprechenden Status Code, welcher mitteilt, dass START erfolgreich gesendet wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while  (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nachdem durch die Applikation TWSR daraufhin überprüft wurde, dass START erfolgreich gesendet wurde, kann es nun weitergehen. Im Fehlerfall könnte beispielsweise eine vom Anwender definierte Fehlerroutine greifen. &lt;br /&gt;
&lt;br /&gt;
Nun muss SLA_W in TWDR geladen werden. Ist dies abgeschlossen, muss wiederum ein spezieller Wert in TWCR geschrieben werden, um der TWI-Logik mitzuteilen, dass die Adresse und der Schreibbefehl aus TWDR gesendet werden können. Unmittelbar nachdem durch den Anwender dann TWINT in TWCR gelöscht wurde (Schreiben einer &#039;1&#039;) sendet das TWI das Adresspaket.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != START)&lt;br /&gt;
  ERROR();                                                                //Fehlerbehandlung&lt;br /&gt;
TWDR = SLA_W;&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT) | (1&amp;lt;&amp;lt;TWEN);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach Abschluss der Sendung wird wiederum TWINT gesetzt in TWSR steht der entsprechende Statuscode, welcher über Erfolg bzw. Misserfolg der Sendung urteilt. In ihm ist auch das ACK-Bit des angesprochenen Slaves enthalten (oder auch nicht, was dann einen Fehler bedeuten würde).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nach der Prüfung von TWSR ob bei der Sendung keine Fehler aufgetreten sind, kann das Datenpaket in TWDR geladen werden. Erneut muss ein spezieller Wert in TWCR geschrieben werden, welcher der Logik sagt, dass ein Datenpaket aus TWDR versendet werden soll. Nach dem Löschen von TWINT wird dieses automatisch versendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != MT_SLA_ACK)&lt;br /&gt;
  ERROR();&lt;br /&gt;
TWDR = DATA;&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT) | (1&amp;lt;&amp;lt;TWEN);&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nachdem TWINT gesetzt wurde kann mit Hilfe von TWSR überprüft werden, ob das Datenpaket erfolgreich gesendet und vom angesprochenen Slave angenommen wurde (ACK-Bit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
 &amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachdem bis hierhin alles funktioniert hat (angenommen), muss nun nur noch ein STOP gesendet werden. Dies erfolgt analog zu den obigen Ausführungen durch Schreiben eines speziellen Wertes in TWCR. Nach dem Löschen von TWINT wird dieses gesendet. Allerdings wird danach TWINT nicht automatisch wieder gesetzt, wie es zuvor immer der Fall war.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != MT_DATA_ACK)&lt;br /&gt;
  ERROR();&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEN)|&lt;br /&gt;
(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkung: Selbstverständlich muss zuvor beim anzusprechenden Slave in TWAR (TWI Adress Register) eine Adresse festgelegt werden, damit er auch gezielt angesprochen werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
== Übertragungsmodi ==&lt;br /&gt;
&lt;br /&gt;
Das TWI kann prinzipiell in vier verschiedenen Modi arbeiten: Master Transmitter (MT), Master Receiver (MR), Slave Transmitter (ST), Slave Receiver (SR). Diese können natürlich alle in einer Anwendung verwendet werden, je nachdem, wie sie es erfordert.&lt;br /&gt;
&lt;br /&gt;
=== Master Transmitter Mode ===&lt;br /&gt;
&lt;br /&gt;
Im MTM wird eine Abfolge von Bytes (Daten) an einen SR gesendet. Um ihn zu benutzen, muss das Adresspaket nach dem gesendeten START eine bestimmte Form aufweisen. Wird SLA+W gesendet, liegt der MTM vor, für SLA+R wäre es der MRM.&lt;br /&gt;
Das Senden eines START gestaltet sich wie folgt (TWCR):&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* TWEN:    Aktivierung des TWI&lt;br /&gt;
* TWSTA:    Senden des START&lt;br /&gt;
* TWINT:    um TWINT zu löschen&lt;br /&gt;
&lt;br /&gt;
Das TWI wartet nun solange, bis der Bus frei ist und sendet dann START. Danach wird TWINT wieder gesetzt und TWSR aktualisiert. Es sollte jetzt 0x08 enthalten. Beim Auslesen des Status-Code müssen die Prescaler-Bits mit Null maskiert werden. Um den MTM zu benutzen, muss SLA+W in TWDR geschrieben werden. Nachdem TWINT gelöscht wurde, wird dies gesendet. TWCR muss dazu die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nachdem SLA+W gesendet und das ACK-Bit empfangen wurde, wird TWINT erneut gesetzt. Der Statuscode in TWSR kann nun unter anderem folgende Formen haben: 0x18, 0x20, 0x38. &lt;br /&gt;
&lt;br /&gt;
Nachdem bis hierhin alles erfolgreich funktioniert hat, kann jetzt ein Datenpaket versendet werden. Dies erfolgt durch Schreiben der Daten in TWDR. TWDR kann nur aktualisiert werden, wenn TWINT gesetzt ist, andernfalls kommt es zu einem Fehler, TWWC (TWI Write Collision Bit) wird gesetzt. Um die Daten zu senden, muss TWINT erneut gelöscht werden. TWCR sollte so aussehen:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Dieses Schema wiederholt sich nun solange, bis alle Daten versendet wurden und ein STOP gesendet werden kann. Dies erfolgt folgendermaßen:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |1    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Ein erneuter Start (REPEATED START) erfolgt durch Schreiben der folgenden Werte in TWCR:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach einem REPEATED START kann der Master denselben Slave erneut kontaktieren oder auch einen anderen, ohne ein STOP zu senden. Der REPEATED START erlaubt dem Master das Wechseln zwischen Slaves, MTM und MRM ohne die Kontrolle über den Bus zu verlieren.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.176 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Master Receiver Mode ===&lt;br /&gt;
&lt;br /&gt;
Im MRM empfängt der Master Daten von einem ST. Zunächst muss wieder START gesendet werden. Das folgende Adresspaket sollte dann SLA+R enthalten.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* TWEN:    Aktivierung des TWI&lt;br /&gt;
* TWSTA:    Senden des START&lt;br /&gt;
* TWINT:    um TWINT zu löschen&lt;br /&gt;
&lt;br /&gt;
Das TWI wartet nun solange, bis der Bus frei ist und sendet dann START. Danach wird TWINT wieder gesetzt und TWSR aktualisiert. Es sollte jetzt 0x08 enthalten. Beim Auslesen des Status-Code müssen die Prescaler-Bits mit Null maskiert werden. Um den MTM zu benutzen, muss SLA+R in TWDR geschrieben werden. Nachdem TWINT gelöscht wurde, wird dies gesendet. TWCR muss dazu die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nachdem SLA+R gesendet und das ACK-Bit empfangen wurde, wird TWINT erneut gesetzt. Der Statuscode in TWSR kann nun unter anderem folgende Formen haben: 0x38, 0x40, 0x48. &lt;br /&gt;
Die empfangenen Daten können aus TWDR gelesen werden, so denn TWINT gesetzt ist. Dieses Schema kann sich bis zum Empfang des letzten Bytes immer wieder wiederholen. Nachdem das letzte Byte empfangen wurde, kann der Master dem Slave durch senden von NACK klar machen, dass keine Daten mehr erwartet werden. Beendet wird der Transfer durch senden von STOP oder REPEATED START.&lt;br /&gt;
Für STOP muss folgendes in TWCR geschrieben werden:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |1    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Für einen REPEATED START muss folgendes in TWCR geschrieben werden:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach einem REPEATED START kann der Master denselben Slave erneut kontaktieren oder auch einen anderen, ohne ein STOP zu senden. Der REPEATED START erlaubt dem Master das Wechseln zwischen Slaves, MTM und MRM ohne die Kontrolle über den Bus zu verlieren.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.179 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Slave Receiver Mode ===&lt;br /&gt;
&lt;br /&gt;
Im SRM werden Daten vom MT empfangen. Um einen Atmega8 im SRM zu betreiben, müssen TWAR und TWCR die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
TWAR:&lt;br /&gt;
Die oberen 7 Bit stellen die Adress dar, an die das TWI antwortet, wenn es von einem Master angesprochen wird. Wenn das LSB (Least Significant Bit) in Form von TWGCE gesetzt ist, antwortet der Slave auch auf allgemeine Rufe (general calls), andernfalls natürlich nicht.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWA6|TWA5|TWA4|TWA3|TWA2|TWA1|TWA0|TWGCE&lt;br /&gt;
 |Hier|steht|dann|die|Adresse|des|Slave!|X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
TWCR:&lt;br /&gt;
TWEN muss zum aktivieren des TWI gesetzt werden. TWEA muss gesetzt werden, damit der Slave antwortet, falls er von einem Master oder gegeben falls durch einen general call angesprochen wird. TWSTA und TWSTO müssen auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |0    |1   |0    |0    |0   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Wenn TWAR und TWCR initialisiert wurden, wartet der Slave ab, bis er mit seiner Adresse bzw. gegebenen falls durch einen generall call angesprochen wird gefolgt von einem Datenrichtungs-Bit. Hierbei steht eine &#039;0&#039; für Schreiben (SR) und eine &#039;1&#039; für Lesen (ST).&lt;br /&gt;
Nachdem die Logik ihre eigene Adresse und ein Schreib-Bit erhalten hat, wird TWINT gesetzt und TWSR beinhaltet den entsprechenden Statuscode. Mit seiner Hilfe kann die Software dann eine sinnvolle Reaktion einleiten. Der Eintritt in den SRM kann auch erfolgen, wenn ein Master sein Vorrecht auf dem Bus verloren hat (0x68, 0x78).&lt;br /&gt;
&lt;br /&gt;
Wenn TWEA während eines Transfers zurückgesetzt wird, wird das TWI ein NACK (Not Acknowledge) auf den Bus nach Empfang des nächsten Bytes geben. Dies kann verwendet werden, wenn der Slave nicht mehr in der Lage ist, mehr Bytes zu empfangen. Solange TWEA &#039;0&#039; ist, reagiert das TWI nicht mehr auf seine eigene Slave-Adresse. Jedoch wird der Bus weiterhin beobachtet und das TWI ist nach dem Setzen von TWEA sofort wieder einsatzbereit. Somit kann dieses Feature verwendet werden, um einen Baustein für eine bestimmte Zeitspanne vom Bus zu nehmen.&lt;br /&gt;
&lt;br /&gt;
In sämtlichen Sleep-Modi (außer Idle Mode) ist der Systemtakt des TWI inaktiv. Dessen zu trotz kann das TWI durch setzen von TWEA allein mit Hilfe des Bustaktes erfassen, wenn es mit seiner Adresse bzw. durch einen general call angesprochen wird. Somit kann das TWI den Controller aufwecken. Während der Aufweck-Phase kann SCL auf L-Pegel gehalten werden wenn TWINT gelöscht ist (Schreiben einer &#039;1&#039;). Der Datenempfang kann wieder im Normalbetrieb stattfinden. Zu beachten ist, dass solange SCL auf L-Pegel ist keine anderen Transmissionen stattfinden können. Wichtig ist, dass TWDR nach dem Aufwecken nicht mehr das letzte Byte, welches auf dem Bus war, enthält.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.182 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Slave Transmitter Mode ===&lt;br /&gt;
&lt;br /&gt;
Im STM werden Daten an einen MR gesendet. Um den Controller im STM zu betreiben, müssen TWAR und TWCR wie folgt initialisiert werden.&lt;br /&gt;
&lt;br /&gt;
TWAR:&lt;br /&gt;
Die oberen 7 Bit stellen die Adress dar, an die das TWI antwortet, wenn es von einem Master angesprochen wird. Wenn das LSB (Least Significant Bit) in Form von TWGCE gesetzt ist, antwortet der Slave auch auf allgemeine Rufe (general calls), andernfalls natürlich nicht.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWA6|TWA5|TWA4|TWA3|TWA2|TWA1|TWA0|TWGCE&lt;br /&gt;
 |Hier|steht|dann|die|Adresse|des|Slave!|X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
TWCR:&lt;br /&gt;
TWEN muss zum aktivieren des TWI gesetzt werden. TWEA muss gesetzt werden, damit der Slave antwortet, falls er von einem Master oder gegeben falls durch einen general call angesprochen wird. TWSTA und TWSTO müssen auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |0    |1   |0    |0    |0   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach der Initialisierung wartet das TWI auf eine Anfrage gefolgt von einem Datenrichtungsbit. Wird das TWI angesprochen wird TWINT gesetzt und TWSR beinhaltet den Statuscode. Mit seiner Hilfe kann das weitere Vorgehen festgelegt werden. Ein Controller kann auch in den STM gelangen, wenn er die Hoheit auf dem Bus an einen anderen Master verliert (0xB0). &lt;br /&gt;
&lt;br /&gt;
Wird TWEA während eines Transfers gesetzt, wird das aktuelle Byte noch fertig gesendet und Status 0xC0 oder 0xC8 tritt ein, je nachdem ob der Master ACK oder NACK nach dem letzten Byte gesendet hatte. Das TWI wird in einen Blockierzustand gehen, unabhängig davon, ob der Master den Transfer fortsetzt. So erhält der Master nur noch &#039;1&#039; auf dem seriellen Bus. Status 0xC8 tritt ein, wenn der Master weitere Daten fordert (durch Senden von ACK), obwohl der Slave bereits das letzte Byte gesendet hat (TWEA &#039;0&#039; und erwartet NACK).&lt;br /&gt;
&lt;br /&gt;
Trotz des Blockierzustandes wird der Bus weiter beobachtet und das TWI kann durch setzen von TWEA jederzeit wieder daran teilnehmen. Somit kann der Slave mit Hilfe von TWEA kurzzeitig vom Bus isoliert werden.&lt;br /&gt;
&lt;br /&gt;
In sämtlichen Sleep-Modi (außer Idle Mode) ist der Systemtakt des TWI inaktiv. Dessen zu trotz kann das TWI durch setzen von TWEA allein mit Hilfe des Bustaktes erfassen, wenn es mit seiner Adresse bzw. durch einen general call angesprochen wird. Somit kann das TWI den Controller aufwecken. Während der Aufweck-Phase kann SCL auf L-Pegel gehalten werden wenn TWINT gelöscht ist (Schreiben einer &#039;1&#039;). Der Datenversand kann wieder im Normalbetrieb stattfinden. Zu beachten ist, dass solange SCL auf L-Pegel ist keine anderen Transmissionen stattfinden können. Wichtig ist, dass TWDR nach dem Aufwecken nicht mehr das letzte Byte, welches auf dem Bus war, enthält.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.185 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den Betriebsart bezogenen Statuscodes gibt es noch zwei, welche davon unabhängig sind.&lt;br /&gt;
Status 0xF8 bedeutet, dass keine relevanten Informationen vorhanden sind, da TWINT nicht gesetzt ist. Dieser Fall tritt bei einem Statuswechsel ein oder wenn TWI im Moment nicht am Bus beteiligt ist.&lt;br /&gt;
&lt;br /&gt;
Status 0x00 steht für einen Busfehler während einer Übertragung. Ursache kann das Senden von START oder STOP zu einem nicht zulässigem Zeitpunkt sein. Bei solch einem Fehler wird TWINT automatisch gesetzt. Um die Fehlerroutine zu verlassen, muss TWSTO gesetzt und TWINT gelöscht werden. Dieses führt dazu, dass das TWI in den nicht adressierten Slave-Modus geht und SDA und SCL wieder freigegeben werden. Es wird kein STOP gesendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Wem das alles zuviel Theorie war und wer das I2C-Interface einmal im Einsatz erleben möchte, dem lege ich die Rubrik ICs &amp;amp; Co ans Herz. Dort wird die Verwendung eines I2C-EEPROMS demonstriert.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken ===&lt;br /&gt;
* [http://www.jtronics.de/elektronik-avr/lib-i2ctwi-avr.html AVR TWI Slave]&lt;br /&gt;
* [http://jump.to/fleury Peter Fleury&#039;s AVR I2C Library]&lt;br /&gt;
&lt;br /&gt;
===I²C-Bausteine===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR]] &lt;br /&gt;
[[Category:Mc-project.de]]&lt;br /&gt;
[[Category:I2C]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47875</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47875"/>
		<updated>2010-05-24T13:09:20Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Nutzung der Funktionen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47874</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47874"/>
		<updated>2010-05-24T13:08:12Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* sms_decode (char* pdu, SMS_DECODE_DATA_T* data) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];	/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;				/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47873</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47873"/>
		<updated>2010-05-24T13:05:49Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Nutzung der Funktionen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47872</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47872"/>
		<updated>2010-05-24T13:05:00Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Voreinstellungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define UART_MAXSTRLEN 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47871</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47871"/>
		<updated>2010-05-24T13:03:19Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* sms_decode (char* pdu, SMS_DECODE_DATA_T* data) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[SMS_MESSAGE_MAX_LEN+1];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[SMS_TELNR_MAX_LEN+1];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[UART_MAXSTRLEN+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47870</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47870"/>
		<updated>2010-05-24T13:01:18Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt; [[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47869</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47869"/>
		<updated>2010-05-24T13:00:35Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47868</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47868"/>
		<updated>2010-05-24T13:00:15Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Download */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 08.05.2010.zip | Software Stand 08.05.2010]]&lt;br /&gt;
[[Media: Hilfe.zip | Doxygen Hilfe des Projektes]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Hilfe.zip&amp;diff=47867</id>
		<title>Datei:Hilfe.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Hilfe.zip&amp;diff=47867"/>
		<updated>2010-05-24T13:00:08Z</updated>

		<summary type="html">&lt;p&gt;Remote1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Software_Stand_08.05.2010.zip&amp;diff=47866</id>
		<title>Datei:Software Stand 08.05.2010.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Software_Stand_08.05.2010.zip&amp;diff=47866"/>
		<updated>2010-05-24T12:59:43Z</updated>

		<summary type="html">&lt;p&gt;Remote1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47865</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47865"/>
		<updated>2010-05-24T12:58:07Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Nutzung der Funktionen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden.&lt;br /&gt;
&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47864</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47864"/>
		<updated>2010-05-24T12:53:03Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Voreinstellungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). &lt;br /&gt;
Ein weiteres wichtiges Makro ist&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste &lt;br /&gt;
* &amp;lt;br&amp;gt; Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR_LIST_MAX 5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden.&lt;br /&gt;
Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47863</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=47863"/>
		<updated>2010-05-24T12:47:50Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,				/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,			/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_RETRIEVE_nTELNR,/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und &amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt; korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */&lt;br /&gt;
	SMS_IDLE			/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46853</id>
		<title>Minila Version MockUp</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46853"/>
		<updated>2010-04-29T05:50:14Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* LEDs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Voting einiger Dinge die im Thread angesprochen wurden ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
(Nach 5 Strichen &amp;quot;|&amp;quot; bitte ein Leerzeichen)&lt;br /&gt;
* USB Versorgt ohne galvanische Trennung der USB-Seite: |&lt;br /&gt;
* USB Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite: ||||| ||&lt;br /&gt;
* ext. Versorgt ohne galvanische Trennung der USB-Seite:&lt;br /&gt;
* ext. Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite:&lt;br /&gt;
Anmerkung: Es steht noch nicht fest ob der Stromverbrauch USB-Konform ist!!!&lt;br /&gt;
&lt;br /&gt;
=== Bestückung ===&lt;br /&gt;
* SMD-Teile bestückt: |||||&lt;br /&gt;
* unbestückt als Bausatz: ||||&lt;br /&gt;
&lt;br /&gt;
=== LEDs ===&lt;br /&gt;
* SMD RGB LED: ||&lt;br /&gt;
* SMD0805 LED: ||&lt;br /&gt;
* 5mm LED: |&lt;br /&gt;
* SMD0805 und 5mm LED (je nach Bestückung): |||&lt;br /&gt;
&lt;br /&gt;
== Wünsche ==&lt;br /&gt;
=== Gehäuse ===&lt;br /&gt;
Fals einer eins gut findet, kann er das ja hier einbinden.&lt;br /&gt;
&lt;br /&gt;
=== Andere Dinge können hier ebenfals hinzugefügt werden ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Feststehende Dinge ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
* Wahrscheinlich ein 3,3V sowie 5V Regler&lt;br /&gt;
* wenn USB-Versorgt abschaltbar um die Spezifikationen zu erfüllen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RAM-Speicher ===&lt;br /&gt;
* 512K*32 Kanäle steht ausser frage&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* GS816036 &lt;br /&gt;
* [ http://de.farnell.com/gsi-technology/gs816032bgt-200/18m-synch-burst-sram-512kx32-smd/dp/1447526 Optional GS816032]&lt;br /&gt;
* [ http://www.cypress.com/?mpn=CY7C1381D-133AXC  Optional CY7C1381D-133AX]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CPLD ===&lt;br /&gt;
* wird der XC95288XL bleiben, da dies nur eine Veränderung und keine Neuentwicklung wird&lt;br /&gt;
* einige Signale werden an anderen Pins angeschlossen und verteilt&lt;br /&gt;
* TQFP144&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
Je nach dem ob per USB versorgt oder nicht wird der FTDI FT2232D im:&lt;br /&gt;
* Bus Powerd Modus oder&lt;br /&gt;
* Self Powerd Modus &lt;br /&gt;
betrieben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Steckverbinder ===&lt;br /&gt;
* Steckerbelegung bleibt beim alten&lt;br /&gt;
* X1-7 wird entfernt, da eh wenig Platz im CPLD ist&lt;br /&gt;
* X8 bleibt erhalten&lt;br /&gt;
* K8 wird dann auch komplett entfernt, da nicht mehr benötigt (alle Signale sind auch an K1 verfügbar)&lt;br /&gt;
* Serienwiderstände in den Datenleitungen wie gehabt&lt;br /&gt;
* Tastköpfe extern wie gehabt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== JTAG ===&lt;br /&gt;
* wird per Steckbrücke an den FTDI anklemmbar sein. Keine Litze notwendig&lt;br /&gt;
* Programmierung über FTDI und &amp;quot;xc3sprog&amp;quot; http://www.mikrocontroller.net/articles/MiniLA#via_USB&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Parallel Port ===&lt;br /&gt;
* nicht vorgesehen&lt;br /&gt;
* Signale als Stiftleiste oder ähnliches herrausgeführt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Layout ===&lt;br /&gt;
* 2 Lagig&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Top-Layer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleTop.png.png|500px]]&lt;br /&gt;
&lt;br /&gt;
* zwischen dem oberen und dem mittleren Steckverbinder ist ~1cm.&lt;br /&gt;
* über der 5mm LED ist die SMD0805 LED angeordnet&lt;br /&gt;
&lt;br /&gt;
== Planungsstand ==&lt;br /&gt;
* 32 Kanäle&lt;br /&gt;
* 100MHz Samplerate&lt;br /&gt;
* 512K Speichertiefe pro Kanal&lt;br /&gt;
* Geschätzter Preis steht noch aus&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/174860#new Hauptthread auf Mikrocontroller.net]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MiniLA Original]&lt;br /&gt;
* [http://minila.sourceforge.net/hw/other/bg/minila_bg_sch.pdf Schaltplan der alten Version]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46852</id>
		<title>Minila Version MockUp</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46852"/>
		<updated>2010-04-29T05:49:50Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Spannungsversorgung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Voting einiger Dinge die im Thread angesprochen wurden ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
(Nach 5 Strichen &amp;quot;|&amp;quot; bitte ein Leerzeichen)&lt;br /&gt;
* USB Versorgt ohne galvanische Trennung der USB-Seite: |&lt;br /&gt;
* USB Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite: ||||| ||&lt;br /&gt;
* ext. Versorgt ohne galvanische Trennung der USB-Seite:&lt;br /&gt;
* ext. Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite:&lt;br /&gt;
Anmerkung: Es steht noch nicht fest ob der Stromverbrauch USB-Konform ist!!!&lt;br /&gt;
&lt;br /&gt;
=== Bestückung ===&lt;br /&gt;
* SMD-Teile bestückt: |||||&lt;br /&gt;
* unbestückt als Bausatz: ||||&lt;br /&gt;
&lt;br /&gt;
=== LEDs ===&lt;br /&gt;
* SMD RGB LED: |&lt;br /&gt;
* SMD0805 LED: ||&lt;br /&gt;
* 5mm LED: |&lt;br /&gt;
* SMD0805 und 5mm LED (je nach Bestückung): |||&lt;br /&gt;
&lt;br /&gt;
== Wünsche ==&lt;br /&gt;
=== Gehäuse ===&lt;br /&gt;
Fals einer eins gut findet, kann er das ja hier einbinden.&lt;br /&gt;
&lt;br /&gt;
=== Andere Dinge können hier ebenfals hinzugefügt werden ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Feststehende Dinge ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
* Wahrscheinlich ein 3,3V sowie 5V Regler&lt;br /&gt;
* wenn USB-Versorgt abschaltbar um die Spezifikationen zu erfüllen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RAM-Speicher ===&lt;br /&gt;
* 512K*32 Kanäle steht ausser frage&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* GS816036 &lt;br /&gt;
* [ http://de.farnell.com/gsi-technology/gs816032bgt-200/18m-synch-burst-sram-512kx32-smd/dp/1447526 Optional GS816032]&lt;br /&gt;
* [ http://www.cypress.com/?mpn=CY7C1381D-133AXC  Optional CY7C1381D-133AX]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CPLD ===&lt;br /&gt;
* wird der XC95288XL bleiben, da dies nur eine Veränderung und keine Neuentwicklung wird&lt;br /&gt;
* einige Signale werden an anderen Pins angeschlossen und verteilt&lt;br /&gt;
* TQFP144&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
Je nach dem ob per USB versorgt oder nicht wird der FTDI FT2232D im:&lt;br /&gt;
* Bus Powerd Modus oder&lt;br /&gt;
* Self Powerd Modus &lt;br /&gt;
betrieben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Steckverbinder ===&lt;br /&gt;
* Steckerbelegung bleibt beim alten&lt;br /&gt;
* X1-7 wird entfernt, da eh wenig Platz im CPLD ist&lt;br /&gt;
* X8 bleibt erhalten&lt;br /&gt;
* K8 wird dann auch komplett entfernt, da nicht mehr benötigt (alle Signale sind auch an K1 verfügbar)&lt;br /&gt;
* Serienwiderstände in den Datenleitungen wie gehabt&lt;br /&gt;
* Tastköpfe extern wie gehabt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== JTAG ===&lt;br /&gt;
* wird per Steckbrücke an den FTDI anklemmbar sein. Keine Litze notwendig&lt;br /&gt;
* Programmierung über FTDI und &amp;quot;xc3sprog&amp;quot; http://www.mikrocontroller.net/articles/MiniLA#via_USB&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Parallel Port ===&lt;br /&gt;
* nicht vorgesehen&lt;br /&gt;
* Signale als Stiftleiste oder ähnliches herrausgeführt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Layout ===&lt;br /&gt;
* 2 Lagig&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Top-Layer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleTop.png.png|500px]]&lt;br /&gt;
&lt;br /&gt;
* zwischen dem oberen und dem mittleren Steckverbinder ist ~1cm.&lt;br /&gt;
* über der 5mm LED ist die SMD0805 LED angeordnet&lt;br /&gt;
&lt;br /&gt;
== Planungsstand ==&lt;br /&gt;
* 32 Kanäle&lt;br /&gt;
* 100MHz Samplerate&lt;br /&gt;
* 512K Speichertiefe pro Kanal&lt;br /&gt;
* Geschätzter Preis steht noch aus&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/174860#new Hauptthread auf Mikrocontroller.net]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MiniLA Original]&lt;br /&gt;
* [http://minila.sourceforge.net/hw/other/bg/minila_bg_sch.pdf Schaltplan der alten Version]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46765</id>
		<title>Minila Version MockUp</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46765"/>
		<updated>2010-04-28T14:47:33Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* LEDs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Voting einiger Dinge die im Thread angesprochen wurden ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
(Nach 5 Strichen &amp;quot;|&amp;quot; bitte ein Leerzeichen)&lt;br /&gt;
* USB Versorgt ohne galvanische Trennung der USB-Seite: &lt;br /&gt;
* USB Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite: |&lt;br /&gt;
* ext. Versorgt ohne galvanische Trennung der USB-Seite:&lt;br /&gt;
* ext. Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite:&lt;br /&gt;
Anmerkung: Es steht noch nicht fest ob der Stromverbrauch USB-Konform ist!!!&lt;br /&gt;
&lt;br /&gt;
=== Bestückung ===&lt;br /&gt;
* SMD-Teile bestückt: |&lt;br /&gt;
* unbestückt als Bausatz:&lt;br /&gt;
&lt;br /&gt;
=== LEDs ===&lt;br /&gt;
* SMD0805 LED:&lt;br /&gt;
* 5mm LED: |&lt;br /&gt;
* SMD0805 und 5mm LED (je nach Bestückung):&lt;br /&gt;
&lt;br /&gt;
== Wünsche ==&lt;br /&gt;
=== Gehäuse ===&lt;br /&gt;
Fals einer eins gut findet, kann er das ja hier einbinden.&lt;br /&gt;
&lt;br /&gt;
=== Andere Dinge können hier ebenfals hinzugefügt werden ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Feststehende Dinge ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
* Wahrscheinlich ein 3,3V sowie 5V Regler&lt;br /&gt;
* wenn USB-Versorgt abschaltbar um die Spezifikationen zu erfüllen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RAM-Speicher ===&lt;br /&gt;
* 512K*32 Kanäle steht ausser frage&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* GS816036 &lt;br /&gt;
* [ http://de.farnell.com/gsi-technology/gs816032bgt-200/18m-synch-burst-sram-512kx32-smd/dp/1447526 Optional GS816032]&lt;br /&gt;
* [ http://www.cypress.com/?mpn=CY7C1381D-133AXC  Optional CY7C1381D-133AX]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CPLD ===&lt;br /&gt;
* wird der XC95288XL bleiben, da dies nur eine Veränderung und keine Neuentwicklung wird&lt;br /&gt;
* einige Signale werden an anderen Pins angeschlossen und verteilt&lt;br /&gt;
* TQFP144&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
Je nach dem ob per USB versorgt oder nicht wird der FTDI FT2232D im:&lt;br /&gt;
* Bus Powerd Modus oder&lt;br /&gt;
* Self Powerd Modus &lt;br /&gt;
betrieben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Steckverbinder ===&lt;br /&gt;
* Steckerbelegung bleibt beim alten&lt;br /&gt;
* X1-7 wird entfernt, da eh wenig Platz im CPLD ist&lt;br /&gt;
* X8 bleibt erhalten&lt;br /&gt;
* K8 wird dann auch komplett entfernt, da nicht mehr benötigt (alle Signale sind auch an K1 verfügbar)&lt;br /&gt;
* Serienwiderstände in den Datenleitungen wie gehabt&lt;br /&gt;
* Tastköpfe extern wie gehabt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== JTAG ===&lt;br /&gt;
* wird per Steckbrücke an den FTDI anklemmbar sein. Keine Litze notwendig&lt;br /&gt;
* Programmierung über FTDI und &amp;quot;xc3sprog&amp;quot; http://www.mikrocontroller.net/articles/MiniLA#via_USB&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Parallel Port ===&lt;br /&gt;
* nicht vorgesehen&lt;br /&gt;
* Signale als Stiftleiste oder ähnliches herrausgeführt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Layout ===&lt;br /&gt;
* 2 Lagig&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Top-Layer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleTop.png.png|500px]]&lt;br /&gt;
&lt;br /&gt;
* zwischen dem oberen und dem mittleren Steckverbinder ist ~1cm.&lt;br /&gt;
* über der 5mm LED ist die SMD0805 LED angeordnet&lt;br /&gt;
&lt;br /&gt;
== Plannungsstand ==&lt;br /&gt;
* 32 Kanäle&lt;br /&gt;
* 100MHz Samplerate&lt;br /&gt;
* 512K Speichertiefe pro Kanal&lt;br /&gt;
* Geschätzter Preis steht noch aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/174860#new Hauptthread auf Mikrocontroller.net]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MiniLA Original]&lt;br /&gt;
* [http://minila.sourceforge.net/hw/other/bg/minila_bg_sch.pdf Schaltplan der alten Version]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46764</id>
		<title>Minila Version MockUp</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46764"/>
		<updated>2010-04-28T14:47:10Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Bestückung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Voting einiger Dinge die im Thread angesprochen wurden ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
(Nach 5 Strichen &amp;quot;|&amp;quot; bitte ein Leerzeichen)&lt;br /&gt;
* USB Versorgt ohne galvanische Trennung der USB-Seite: &lt;br /&gt;
* USB Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite: |&lt;br /&gt;
* ext. Versorgt ohne galvanische Trennung der USB-Seite:&lt;br /&gt;
* ext. Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite:&lt;br /&gt;
Anmerkung: Es steht noch nicht fest ob der Stromverbrauch USB-Konform ist!!!&lt;br /&gt;
&lt;br /&gt;
=== Bestückung ===&lt;br /&gt;
* SMD-Teile bestückt: |&lt;br /&gt;
* unbestückt als Bausatz:&lt;br /&gt;
&lt;br /&gt;
=== LEDs ===&lt;br /&gt;
* SMD0805 LED:&lt;br /&gt;
* 5mm LED:&lt;br /&gt;
* SMD0805 und 5mm LED (je nach Bestückung):&lt;br /&gt;
&lt;br /&gt;
== Wünsche ==&lt;br /&gt;
=== Gehäuse ===&lt;br /&gt;
Fals einer eins gut findet, kann er das ja hier einbinden.&lt;br /&gt;
&lt;br /&gt;
=== Andere Dinge können hier ebenfals hinzugefügt werden ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Feststehende Dinge ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
* Wahrscheinlich ein 3,3V sowie 5V Regler&lt;br /&gt;
* wenn USB-Versorgt abschaltbar um die Spezifikationen zu erfüllen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RAM-Speicher ===&lt;br /&gt;
* 512K*32 Kanäle steht ausser frage&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* GS816036 &lt;br /&gt;
* [ http://de.farnell.com/gsi-technology/gs816032bgt-200/18m-synch-burst-sram-512kx32-smd/dp/1447526 Optional GS816032]&lt;br /&gt;
* [ http://www.cypress.com/?mpn=CY7C1381D-133AXC  Optional CY7C1381D-133AX]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CPLD ===&lt;br /&gt;
* wird der XC95288XL bleiben, da dies nur eine Veränderung und keine Neuentwicklung wird&lt;br /&gt;
* einige Signale werden an anderen Pins angeschlossen und verteilt&lt;br /&gt;
* TQFP144&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
Je nach dem ob per USB versorgt oder nicht wird der FTDI FT2232D im:&lt;br /&gt;
* Bus Powerd Modus oder&lt;br /&gt;
* Self Powerd Modus &lt;br /&gt;
betrieben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Steckverbinder ===&lt;br /&gt;
* Steckerbelegung bleibt beim alten&lt;br /&gt;
* X1-7 wird entfernt, da eh wenig Platz im CPLD ist&lt;br /&gt;
* X8 bleibt erhalten&lt;br /&gt;
* K8 wird dann auch komplett entfernt, da nicht mehr benötigt (alle Signale sind auch an K1 verfügbar)&lt;br /&gt;
* Serienwiderstände in den Datenleitungen wie gehabt&lt;br /&gt;
* Tastköpfe extern wie gehabt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== JTAG ===&lt;br /&gt;
* wird per Steckbrücke an den FTDI anklemmbar sein. Keine Litze notwendig&lt;br /&gt;
* Programmierung über FTDI und &amp;quot;xc3sprog&amp;quot; http://www.mikrocontroller.net/articles/MiniLA#via_USB&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Parallel Port ===&lt;br /&gt;
* nicht vorgesehen&lt;br /&gt;
* Signale als Stiftleiste oder ähnliches herrausgeführt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Layout ===&lt;br /&gt;
* 2 Lagig&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Top-Layer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleTop.png.png|500px]]&lt;br /&gt;
&lt;br /&gt;
* zwischen dem oberen und dem mittleren Steckverbinder ist ~1cm.&lt;br /&gt;
* über der 5mm LED ist die SMD0805 LED angeordnet&lt;br /&gt;
&lt;br /&gt;
== Plannungsstand ==&lt;br /&gt;
* 32 Kanäle&lt;br /&gt;
* 100MHz Samplerate&lt;br /&gt;
* 512K Speichertiefe pro Kanal&lt;br /&gt;
* Geschätzter Preis steht noch aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/174860#new Hauptthread auf Mikrocontroller.net]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MiniLA Original]&lt;br /&gt;
* [http://minila.sourceforge.net/hw/other/bg/minila_bg_sch.pdf Schaltplan der alten Version]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46762</id>
		<title>Minila Version MockUp</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Minila_Version_MockUp&amp;diff=46762"/>
		<updated>2010-04-28T14:46:08Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Spannungsversorgung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Voting einiger Dinge die im Thread angesprochen wurden ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
(Nach 5 Strichen &amp;quot;|&amp;quot; bitte ein Leerzeichen)&lt;br /&gt;
* USB Versorgt ohne galvanische Trennung der USB-Seite: &lt;br /&gt;
* USB Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite: |&lt;br /&gt;
* ext. Versorgt ohne galvanische Trennung der USB-Seite:&lt;br /&gt;
* ext. Versorgt mit galvanische Trennung (ADuM4160) der USB-Seite:&lt;br /&gt;
Anmerkung: Es steht noch nicht fest ob der Stromverbrauch USB-Konform ist!!!&lt;br /&gt;
&lt;br /&gt;
=== Bestückung ===&lt;br /&gt;
* SMD-Teile bestückt:&lt;br /&gt;
* unbestückt als Bausatz:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== LEDs ===&lt;br /&gt;
* SMD0805 LED:&lt;br /&gt;
* 5mm LED:&lt;br /&gt;
* SMD0805 und 5mm LED (je nach Bestückung):&lt;br /&gt;
&lt;br /&gt;
== Wünsche ==&lt;br /&gt;
=== Gehäuse ===&lt;br /&gt;
Fals einer eins gut findet, kann er das ja hier einbinden.&lt;br /&gt;
&lt;br /&gt;
=== Andere Dinge können hier ebenfals hinzugefügt werden ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Feststehende Dinge ==&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
* Wahrscheinlich ein 3,3V sowie 5V Regler&lt;br /&gt;
* wenn USB-Versorgt abschaltbar um die Spezifikationen zu erfüllen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RAM-Speicher ===&lt;br /&gt;
* 512K*32 Kanäle steht ausser frage&lt;br /&gt;
* TQFP100 0,65mm Pinabstand&lt;br /&gt;
* GS816036 &lt;br /&gt;
* [ http://de.farnell.com/gsi-technology/gs816032bgt-200/18m-synch-burst-sram-512kx32-smd/dp/1447526 Optional GS816032]&lt;br /&gt;
* [ http://www.cypress.com/?mpn=CY7C1381D-133AXC  Optional CY7C1381D-133AX]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CPLD ===&lt;br /&gt;
* wird der XC95288XL bleiben, da dies nur eine Veränderung und keine Neuentwicklung wird&lt;br /&gt;
* einige Signale werden an anderen Pins angeschlossen und verteilt&lt;br /&gt;
* TQFP144&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
Je nach dem ob per USB versorgt oder nicht wird der FTDI FT2232D im:&lt;br /&gt;
* Bus Powerd Modus oder&lt;br /&gt;
* Self Powerd Modus &lt;br /&gt;
betrieben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Steckverbinder ===&lt;br /&gt;
* Steckerbelegung bleibt beim alten&lt;br /&gt;
* X1-7 wird entfernt, da eh wenig Platz im CPLD ist&lt;br /&gt;
* X8 bleibt erhalten&lt;br /&gt;
* K8 wird dann auch komplett entfernt, da nicht mehr benötigt (alle Signale sind auch an K1 verfügbar)&lt;br /&gt;
* Serienwiderstände in den Datenleitungen wie gehabt&lt;br /&gt;
* Tastköpfe extern wie gehabt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== JTAG ===&lt;br /&gt;
* wird per Steckbrücke an den FTDI anklemmbar sein. Keine Litze notwendig&lt;br /&gt;
* Programmierung über FTDI und &amp;quot;xc3sprog&amp;quot; http://www.mikrocontroller.net/articles/MiniLA#via_USB&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Parallel Port ===&lt;br /&gt;
* nicht vorgesehen&lt;br /&gt;
* Signale als Stiftleiste oder ähnliches herrausgeführt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Layout ===&lt;br /&gt;
* 2 Lagig&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Top-Layer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Bild:MockUpMiniLALayoutEagleTop.png.png|500px]]&lt;br /&gt;
&lt;br /&gt;
* zwischen dem oberen und dem mittleren Steckverbinder ist ~1cm.&lt;br /&gt;
* über der 5mm LED ist die SMD0805 LED angeordnet&lt;br /&gt;
&lt;br /&gt;
== Plannungsstand ==&lt;br /&gt;
* 32 Kanäle&lt;br /&gt;
* 100MHz Samplerate&lt;br /&gt;
* 512K Speichertiefe pro Kanal&lt;br /&gt;
* Geschätzter Preis steht noch aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/174860#new Hauptthread auf Mikrocontroller.net]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MiniLA Original]&lt;br /&gt;
* [http://minila.sourceforge.net/hw/other/bg/minila_bg_sch.pdf Schaltplan der alten Version]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=46552</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=46552"/>
		<updated>2010-04-23T17:36:18Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=46551</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=46551"/>
		<updated>2010-04-23T17:35:26Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 ([http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 siehe MyAVR]).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
extern foo (uint8_t dat);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die eigentliche Funktion kann in dieDatei main.c geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45546</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45546"/>
		<updated>2010-03-31T08:52:59Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmeag8. Schaut einfach einmal bei [http://shop.myavr.de/index.php?sp=artlist_kat.sp.php&amp;amp;katID=8 myAVR] vorbei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45509</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45509"/>
		<updated>2010-03-30T15:38:09Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Nutzung der Funktionen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
// main loop&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45508</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45508"/>
		<updated>2010-03-30T15:37:39Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus &#039;&#039;&#039;Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45507</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45507"/>
		<updated>2010-03-30T15:37:19Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* SMS_MSG sms_state_machine(void) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die &#039;&#039;&#039;Schlüsselwörter müssen dabei immer aus Kleinbuchstaben&#039;&#039;&#039; bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45499</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45499"/>
		<updated>2010-03-30T11:35:22Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Voreinstellungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus Kleinbuchstaben bestehen. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45498</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45498"/>
		<updated>2010-03-30T11:35:04Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Voreinstellungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus Kleinbuchstaben bestehen. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine Kleine Reserve für Steuerzeichen wie new line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45497</id>
		<title>Versenden von SMS mittels Mobiltelefon</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versenden_von_SMS_mittels_Mobiltelefon&amp;diff=45497"/>
		<updated>2010-03-30T11:17:46Z</updated>

		<summary type="html">&lt;p&gt;Remote1: /* Voreinstellungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &#039;&#039;&#039;Einleitung&#039;&#039;&#039; ==&lt;br /&gt;
Im Forum kommt immer häufiger die Frage &amp;quot;Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?&amp;quot;. Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden.&lt;br /&gt;
Die Software beinhaltet unter anderem:&lt;br /&gt;
* Reaktion auf einen bestimmten Anrufer&lt;br /&gt;
* Versand von Textnachrichten im PDU Format&lt;br /&gt;
* Auslesen von Textnachrichten im PDU Format und Decodierung&lt;br /&gt;
* Auslesen des aktuellen Datums und der Zeit des Mobiltelefons&lt;br /&gt;
* Anzeigen von Text auf dem Display des Mobiltelefons&lt;br /&gt;
* Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter&lt;br /&gt;
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das Verbraucht zwar mehr Speicher, trägt aber meines Erachtens mehr zum Verständnis bei.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Hardware&#039;&#039;&#039; ==&lt;br /&gt;
[[Bild:ATmega8-Board.png|thumb|400px|Schaltplan des ATmega8 Boards mit I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C Temperatursensor]]&lt;br /&gt;
[[Bild:ATmega8-Board3D.png|thumb|250px|3D Ansicht des ATmega8 Boards]]&lt;br /&gt;
&lt;br /&gt;
Ich arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich.&lt;br /&gt;
&lt;br /&gt;
Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist Hight-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (Hight-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein.&lt;br /&gt;
&lt;br /&gt;
Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Software&#039;&#039;&#039; ==&lt;br /&gt;
Allgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Der UART]) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt.&lt;br /&gt;
&lt;br /&gt;
c&lt;br /&gt;
AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Das PDU Format&#039;&#039;&#039; ===&lt;br /&gt;
Viele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
AT+CMGS=22&amp;lt;cr&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
0001000B811026214365F700000AC8309BFD065DCB6C3A&amp;lt;subst&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zeichen &amp;lt;cr&amp;gt; und &amp;lt;subst&amp;gt; sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen &amp;lt;cr&amp;gt; stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und &amp;lt;subst&amp;gt; ein so genanntes substitute (dezimal 26).&lt;br /&gt;
Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann.&lt;br /&gt;
Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Vorgehen beim Umwandeln einer Zeichenkette in das PDU Format&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;ASCII Zeichen&#039;&#039;&#039; || H || a || l || l || o || || W || e || l || t&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; |&#039;&#039;&#039;8 Bit Binär&#039;&#039;&#039; || 01001000 || 01100001 || 01101100 || 01101100 || 01101111 || 00100000 || 01010111 || 01100101 || 01101100 || 01110100&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;7 Bit Biär&#039;&#039;&#039; || 1001000 || 110000&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 11011&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 110&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 01&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt; || 1101100 || 111010&amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Binär PDU&#039;&#039;&#039; || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;/span&amp;gt;1001000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;110000|| &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;100&#039;&#039;&#039;&amp;lt;/span&amp;gt;11011 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1111&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;00000&#039;&#039;&#039;&amp;lt;/span&amp;gt;110 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;010111&#039;&#039;&#039;&amp;lt;/span&amp;gt;01 || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;1100101&#039;&#039;&#039;&amp;lt;/span&amp;gt;1 || || &amp;lt;span style=&amp;quot;color:red;&amp;quot;&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;/span&amp;gt;1101100 || &amp;lt;span style=&amp;quot;color:blue;&amp;quot;&amp;gt;&#039;&#039;&#039;00&#039;&#039;&#039;&amp;lt;/span&amp;gt;111010&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background-color:#B3B7FF;&amp;quot; | &#039;&#039;&#039;8 Bit Hex PDU&#039;&#039;&#039; || C8 || 30 || 9B || FD || 06 || 5D || CB ||  || 6C || 3A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Funktionsbeschreibung&#039;&#039;&#039; ===&lt;br /&gt;
Ich beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_init(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_time(	unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
unsigned char year=0;&lt;br /&gt;
unsigned char month=0;&lt;br /&gt;
unsigned char day=0;&lt;br /&gt;
unsigned char hour=0;&lt;br /&gt;
unsigned char minute=0;&lt;br /&gt;
unsigned char second=0;&lt;br /&gt;
sms_time (&amp;amp;year, &amp;amp;month, &amp;amp;day, &amp;amp;hour, &amp;amp;minute, &amp;amp;second);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_send(char* zielnr, char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(SMS_TELNR,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine).&lt;br /&gt;
Der Aufruf kann auch direkt erfolgen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_send(&amp;quot;01621234567&amp;quot;,&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_decode (char* pdu, SMS_DECODE_DATA_T* data)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab.&lt;br /&gt;
Die Datenstruktur ist dabei folgendermaßen aufgebaut:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];		/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;		/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define uart_maxstrlen 160&lt;br /&gt;
...&lt;br /&gt;
SMS_DECODE_DATA_T sms_dec_data;&lt;br /&gt;
char sms_tmp[uart_maxstrlen+1]={&#039;0&#039;};&lt;br /&gt;
int sms_index=0;&lt;br /&gt;
int dummy=0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;AT+CMGR=%i\r\n&amp;quot;,sms_index);&lt;br /&gt;
gets(sms_tmp);	// führendes \r\n verwerfen&lt;br /&gt;
scanf(&amp;quot;+CMGR: %i,,%i\r\n%s\r\n&amp;quot;,&amp;amp;dummy,&amp;amp;dummy,sms_tmp);&lt;br /&gt;
...&lt;br /&gt;
sms_decode(sms_tmp,&amp;amp;sms_dec_data);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;sms_display_text(char* nachricht)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar.&lt;br /&gt;
Beispielaufruf:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
sms_display_text(&amp;quot;Hallo Welt&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;SMS_MSG sms_state_machine(void)&#039;&#039;&#039;====&lt;br /&gt;
Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct SMS_CMD_LIST_S{&lt;br /&gt;
	char cmd[10];			/**&amp;lt; Zeichenkette für Kommando */&lt;br /&gt;
	uint8_t (*fp)(uint8_t dat);	/**&amp;lt; Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */&lt;br /&gt;
}SMS_CMD_LIST_T;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c.&lt;br /&gt;
Beispielhaft könnte diese wie folgt aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
const SMS_CMD_LIST_T sms_cmd_list[] = {&lt;br /&gt;
	{&amp;quot;set&amp;quot;,sms_cmdset},&lt;br /&gt;
	{&amp;quot;test&amp;quot;,sms_cmdtest}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Schlüsselwörter müssen dabei immer aus Kleinbuchstaben bestehen. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Eine eingehende textnachricht mit dem Inhalt &amp;quot;set, test&amp;quot; würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen.&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Verwendung der Bibliothek in eigenen Projekten&#039;&#039;&#039;===&lt;br /&gt;
Die Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden.&lt;br /&gt;
====&#039;&#039;&#039;Voreinstellungen&#039;&#039;&#039;====&lt;br /&gt;
Die Bausrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* definiert Baudrate für serielle Schnittstelle&lt;br /&gt;
*/&lt;br /&gt;
#define UART_BAUD 19200UL&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Definiert die maximale Anzahl von Zeichen, welche über die &lt;br /&gt;
&lt;br /&gt;
Rx-Interruptroutine empfangen werden können.&lt;br /&gt;
* &amp;lt;br&amp;gt; Dient damit auch zum Festlegen der Größe der globalen Variable /ref &lt;br /&gt;
&lt;br /&gt;
uart_string.&lt;br /&gt;
*/&lt;br /&gt;
#define uart_maxstrlen 380&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;math&amp;gt;min Anz = 2\cdot\left(160-\frac{160}8\right)+60 = 340&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Adressat, an welche SMS geschickt werden soll &lt;br /&gt;
* &amp;lt;br&amp;gt; (immer führende 0 mitschreiben, NICHT +49)&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_TELNR &amp;quot;01623456789&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren&lt;br /&gt;
*/&lt;br /&gt;
#define SMS_DELIMITER &amp;quot;,;: &amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Nutzung der Funktionen&#039;&#039;&#039;====&lt;br /&gt;
Neben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)&lt;br /&gt;
*/&lt;br /&gt;
typedef enum {&lt;br /&gt;
	SMS_OK,			/**&amp;lt; OK von Mobiltelefon empfangen */&lt;br /&gt;
	SMS_ERROR,		/**&amp;lt; ERROR von Mobiltelefon empgangen */&lt;br /&gt;
	SMS_MSG_DECODE,		/**&amp;lt; Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */&lt;br /&gt;
	SMS_INCOMING_RING,	/**&amp;lt; eingehender Anruf */&lt;br /&gt;
	SMS_CANCEL_RING,	/**&amp;lt; eingehender Anruf wurde abgewiesen */&lt;br /&gt;
	SMS_REQUEST_TELNR,	/**&amp;lt; Telefonnummer des eingehenden Anruft wurde abgefragt */&lt;br /&gt;
	SMS_RETRIEVE_TELNR,	/**&amp;lt; Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR verglichen */&lt;br /&gt;
	SMS_IDLE		/**&amp;lt; empfangene Zeichenkette wurde nicht in sms_state_machine &amp;quot;gefunden&amp;quot; (kein Eintrag) */&lt;br /&gt;
} SMS_MSG;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint8_t flag;&lt;br /&gt;
while(1){&lt;br /&gt;
	flag = sms_state_machine();&lt;br /&gt;
	if (flag == SMS_RETRIEVE_TELNR){&lt;br /&gt;
		// mache irgend etwas&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* @brief &lt;br /&gt;
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht &lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	uint8_t year;	/**&amp;lt; Jahresangabe YY */&lt;br /&gt;
	uint8_t month;	/**&amp;lt; Monatsangabe MM */&lt;br /&gt;
	uint8_t day;	/**&amp;lt; Tagangabe DD */&lt;br /&gt;
	uint8_t hour;	/**&amp;lt; Stundenangabe hh */&lt;br /&gt;
	uint8_t minute;	/**&amp;lt; Minutenangabe mm */&lt;br /&gt;
	uint8_t second;	/**&amp;lt; Sekundenangabe ss */&lt;br /&gt;
} DATE_T;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* @brief&lt;br /&gt;
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht&lt;br /&gt;
*/&lt;br /&gt;
typedef struct {&lt;br /&gt;
	char nachricht[161];	/**&amp;lt; decodierte PDU Nachricht */&lt;br /&gt;
	char telnr[16];			/**&amp;lt; Telefonnummer des Absenders */&lt;br /&gt;
	DATE_T date;			/**&amp;lt; Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */&lt;br /&gt;
} SMS_DECODE_DATA_T; &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Download&#039;&#039;&#039; ==&lt;br /&gt;
[[Media: Software Stand 22.03.2010.zip | Software Stand 22.03.2010]]&amp;lt;p&amp;gt;&lt;br /&gt;
[[Media: AT Command Set For L55 Siemens Mobile Phones And Modems.pdf|AT Command Set For L55 Siemens Mobile Phones And Modems]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: 3GPP 23.038 Alphabets ans language-specific information.zip| Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: GSM11-14V5-2-0.pdf|Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Media: Application Note 323 - Interfacing GSM modems.pdf|ATMEL Application Note 323 - Interfacing GSM modems]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Quellen&#039;&#039;&#039; ==&lt;br /&gt;
===&#039;&#039;&#039;Allgmeine Quellen zum Thema&#039;&#039;&#039;===&lt;br /&gt;
* [http://twit88.com/home/utility/sms-pdu-encode-decode Online PDU Encoder und Decoder] &lt;br /&gt;
* [http://www.dreamfabric.com/sms/ SMS and the PDU Format]&lt;br /&gt;
* [http://www.mdetroy.de/reload.html?/hp_files/prog/s45/pdu.htm SMS PDU Dokumentation]&lt;br /&gt;
* [http://www.allpinouts.org/index.php/Siemens_Slim_Lumberg_%28A55,_C55,_S55,_SL55,_ST55,_M55%29 Siemens Slim Linburg Steckerbelegung]&lt;br /&gt;
* [http://www.3gpp.org/ftp/Specs/html-info/23038.htm 3GPP: Alphabets ans language-specific information]&lt;br /&gt;
* [https://bugs.cihar.com/file_download.php?file_id=86&amp;amp;type=bug Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc8016.pdf ATMEL: Application Note 323 - Interfacing GSM modems]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;Forenbeiträge&#039;&#039;&#039;===&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/172516 Forumsbeitrag zu diesem Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/149989#new Beitrag zum versenden von SMS mit BASCOM]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/38862#new Sourcecode von Ulrich Radig zum SMS-Versandt]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Projekte]]&lt;/div&gt;</summary>
		<author><name>Remote1</name></author>
	</entry>
</feed>