<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>橋本商会 &#187; AVR</title>
	<atom:link href="http://shokai.org/blog/archives/tag/avr/feed" rel="self" type="application/rss+xml" />
	<link>http://shokai.org/blog</link>
	<description>なんか作ったりした記録を忘れないうちに書くblog</description>
	<lastBuildDate>Mon, 06 Feb 2012 13:32:44 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com/" />
			<item>
		<title>Mac OSXにおける近代的なAVRマイコン開発環境</title>
		<link>http://shokai.org/blog/archives/5557</link>
		<comments>http://shokai.org/blog/archives/5557#comments</comments>
		<pubDate>Mon, 13 Jun 2011 15:01:55 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168p]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[usbasp]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5557</guid>
		<description><![CDATA[久しぶりにAtmel AVRマイコンを直に使うプロジェクトをやるので、環境を整えてみた。@rain_yukizoraと@qt_fbが色々教えてくれた。 これが最強の組み合わせだ！！ Mac OSX Snow Leopar [...]]]></description>
			<content:encoded><![CDATA[<p>
久しぶりにAtmel AVRマイコンを直に使うプロジェクトをやるので、環境を整えてみた。<a href="http://twitter.com/rain_yukizora">@rain_yukizoraと<a href="http://twitter.com/qt_fb">@qt_fb</a>が色々教えてくれた。<br />
<br />
<br />
<br />
これが最強の組み合わせだ！！<br />
<br />
<ul>
  <li>Mac OSX Snow Leopard</li>
  <li><a href="http://www.obdev.at/products/crosspack/index.html">Cross Pack for AVR</a>に入っているavr-gcc</li>
  <li><a href="http://www.macports.org/">macports</a>でインストールしたavrdude</li>
  <li><a href="http://www.aitendo.co.jp/product/2312">aitendoで売ってるusbasp</a></li>
  <li>秋月やマルツで売っているATMega168か168pか328p</li>
</ul>
<br />
この記事では、MacでのAVRマイコン開発環境の構築と、ATMega168pでLEDを1秒間隔で点滅させるプログラムを作成して、マイコンに書き込んで動作させる所までを解説します。<br />
<br />
<br />
Macbook Air + usbasp + ATMega168pで開発しているところ<br />
<a href="http://www.flickr.com/photos/shokai/5827925458/" title="AVR and Mac by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3640/5827925458_fac78d8478.jpg" width="500" height="375" alt="AVR and Mac"></a><br />
<br />
<br />
<br />
■Cross Pack for AVRをインストールする<br />
<a href="http://www.obdev.at/products/crosspack/index.html">CrossPack &#8211; A Development Environment for Atmel’s AVR Microcontrollers</a><br />
ここからダウンロードしてインストールする。<br />
普通は /usr/local/CrossPack-AVR にインストールされるはず。<br />
<br />
<br />
■usbaspを買う<br />
<a href="http://www.aitendo.co.jp/product/2312">aitendoで売ってるusbasp</a>を買う。<br />
これはMacからAVRマイコンに書き込みをする機械(writer)で、USBで動作するライターの中で最も安いし対応デバイスも多いのでオススメ。<br />
朝買ってすぐ銀行に振りこんだら昼には発送されてた。<br />
<br />
<br />
■XCodeをインストールする<br />
次の項目のmacportsのインストールのために、XCodeが必要なのでインストールする。<br />
<a href="https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=20792">Developer Downloads &amp; ADC Program Assets</a><br />
<br />
有料のXCode4が最新だけど、無料の3系でも良い。<br />
<br />
<br />
■Macportsをインストールする<br />
<a href="http://www.macports.org/">macports.org</a>からダウンロードしてインストールする。<br />
<br />
<br />
■macportsとCross Pack for AVRのPATHを通す<br />
$HOME/.profile を開く（無ければ作る）<br />
<br />
これを下の方に書く<br />
<pre class="prettyprint">
export PATH=$PATH:/opt/local/bin<br />
export PATH=$PATH:/usr/local/CrossPack-AVR/bin<br />
</pre>
<br />
新しいterminalを開いて、PATHがセットされているか確かめる。<br />
<pre>
echo $PATH<br />
</pre>
<br />
<br />
■macportsでavrdudeをインストールする<br />
Cross Pack for AVRに入っているavrdudeはUSBで使えないので、USBで使えるavrdudeを作る。<br />
<pre>
sudo port install git-core libusb avrdude<br />
which avrdude<br />
</pre>
<br />
/opt/local/bin/avrdude が出てくればok。Cross Packの方が出てきたら、前のPATHの設定の順序が間違っている。<br />
<br />
（homebrewでもavrdudeがインストールできるが、libusbを先にインストールしていても使えない。よくわからない。）<br />
<br />
<br />
■avrdude.confにATMega168pのデバイス設定を追加する<br />
ATMega168pを使う人だけ。168や328pを使うなら必要ない。<br />
<a href="https://github.com/shokai/atmel-avrgcc-study">https://github.com/shokai/atmel-avrgcc-study</a>からavrdude.confをダウンロードしてきて、 /opt/local/share/avrdude.confと入れ替える。<br />
<br />
<pre class="prettyprint">
git clone git://github.com/shokai/atmel-avrgcc-study.git<br />
sudo cp /opt/local/etc/avrdude.conf /opt/local/etc/avrdude.conf.bak<br />
sudo cp atmel-avrgcc-study/avrdude.conf /opt/local/etc/avrdude.conf<br />
</pre>
<br />
このavrdude.confはmacportsでインストールしたavrdude.confに、<a href="http://www.geocities.jp/arduino_diecimila/bootloader/index.html">Kimio Kosakaさんが作ったavrdude.conf</a>にあったatmega168pの設定を追加した物です。<br />
<br />
<br />
<br />
<br />
これで環境は整ったので、プログラムを書く。<br />
俺が作ったプログラムは <a href="https://github.com/shokai/atmel-avrgcc-study/tree/master/28pin/led_blink">https://github.com/shokai/atmel-avrgcc-study/tree/master/28pin/led_blink</a>にある。これをそのまま書きこんで動かしても良いと思う<br />
<br />
■avr-gccプロジェクトを作る<br />
LEDを点滅させるプロジェクトを作る<br />
<pre>
avr-project led_blink<br />
cd led_blink/firmware<br />
make<br />
</pre>
いきなりコンパイルしてみた。何も修正していなければエラーが無いのでコンパイルはできるはず。<br />
xcode用のファイルも生成されるが、xcodeを使っても全く意味が無いので無視する。<br />
<br />
<br />
■ATMega168pで回路を組む<br />
<br />
写真を見て回路を組む。<br />
左の2つのLED（PB0, PD7）が交互に1秒ごとに点滅する。右のLED(PB1)はスイッチ(PB2)を押している間だけ点灯する。<br />
<a href="http://www.flickr.com/photos/shokai/5827676060/" title="R0015973 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3180/5827676060_510090a178.jpg" width="500" height="375" alt="R0015973"></a><a href="http://www.flickr.com/photos/shokai/5827125983/" title="R0015976 by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2055/5827125983_7a2a628156.jpg" width="500" height="375" alt="R0015976"></a><br />
<br />
<br />
ATMega168pのピン配置はこれ。VCC(AVCC)とGNDを接続する。<br />
<a href="http://www.flickr.com/photos/shokai/5827679654/" title="atmega168 pin assign by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3288/5827679654_530ba7d0b4.jpg" width="462" height="204" alt="atmega168 pin assign"></a><br />
<br />
<br />
usbaspのケーブルの穴側から見たピン配置はこうなっている。<br />
RESET,MISO,MOSI,SCKをAVRライターと接続する。VCCとGNDは回路のそれぞれと接続する。<br />
<a href="http://www.flickr.com/photos/shokai/5827126155/" title="R0015977 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3164/5827126155_50b46b8172_m.jpg" width="240" height="216" alt="R0015977"></a><br />
<br />
<br />
<br />
■Makefileを修正する<br />
修正する箇所はDEVICE,CLOCK,PROGRAMMER,FUSESの4つ。<br />
<pre class="prettyprint">
DEVICE     = atmega168p<br />
CLOCK      = 8000000<br />
PROGRAMMER = -c usbasp<br />
FUSES      = -U hfuse:w:0b11011111:m -U lfuse:w:0b11100010:m<br />
</pre>
ATMega168の時はDEVICE = atmega168にする。<br />
<br />
ここに完成品がある <a href="https://github.com/shokai/atmel-avrgcc-study/blob/master/28pin/led_blink/Makefile">https://github.com/shokai/atmel-avrgcc-study/blob/master/28pin/led_blink/Makefile</a><br />
<br />
fusebitの設定については<a href="http://shokai.org/blog/archives/1185">橋本商会 » ATmega168のクロックを内蔵8Mhzに切り替える</a>に書いた。<br />
<br />
<br />
<br />
■プログラムを書く<br />
<a href="https://github.com/shokai/atmel-avrgcc-study/blob/master/28pin/led_blink/main.c">main.c</a> を書く<br />
<pre class="prettyprint">
#include &lt;avr/io.h&gt;<br />
#include &lt;util/delay.h&gt;<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
#define NULL '\0'<br />
#define sbi(BYTE,BIT) BYTE|=_BV(BIT)<br />
#define cbi(BYTE,BIT) BYTE&amp;=~_BV(BIT)<br />
<br />
#define LED0_ON() sbi(PORTB, PB0)<br />
#define LED0_OFF() cbi(PORTB, PB0)<br />
#define LED1_ON() sbi(PORTD, PD7)<br />
#define LED1_OFF() cbi(PORTD, PD7)<br />
#define LED2_ON() sbi(PORTB, PB1)<br />
#define LED2_OFF() cbi(PORTB, PB1)<br />
<br />
void check_sw(void){<br />
  if(PINB&amp;_BV(PB2)) LED2_ON();<br />
  else LED2_OFF();<br />
}<br />
<br />
<br />
int main(void)<br />
{<br />
  DDRB = 0b00000011;<br />
  DDRD = 0b10000000;<br />
  LED2_ON();<br />
  for(;;){<br />
    LED0_ON();<br />
    LED1_OFF();<br />
    check_sw();<br />
    _delay_ms(1000);<br />
    LED0_OFF();<br />
    LED1_ON();<br />
    check_sw();<br />
    _delay_ms(1000);<br />
  }<br />
  return 0;<br />
}<br />
</pre>
<br />
出力方向レジスタを指定する時は0bで2進数で書くと楽。<br />
LED点滅の1秒（1000ミリ秒）のdelayはutil/delay.hを使った。<br />
<br />
<br />
<br />
■コンパイルする<br />
<pre>
make<br />
</pre>
エラーがあるか確かめられる。<br />
<br />
<br />
<br />
■ヒューズビットを書きこむ<br />
Makefileで指定した、内蔵クロック8MHz駆動のfusebitを書きこむ。<br />
<pre>
make fuse<br />
</pre>
この操作は1回で良い。<br />
<br />
<br />
<br />
■プログラムを書き込む<br />
<pre>
make flash<br />
</pre>
usbaspが書きこんでくれる。<br />
avrdudeがSCKを使えていないというメッセージが出るが、書き込める。<br />
<br />
usbaspが電源も供給してくれるので、回路にACアダプタや電池などの他の電源は接続してはならない。<br />
usbaspの電源供給は基板上のjumper pinを抜けばOFFにできる。<br />
<br />
<br />
これでAVRマイコンをMacで開発できる環境が整った。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5557/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>avr-gccのレジスタ操作で16進数とか使わない方法</title>
		<link>http://shokai.org/blog/archives/1270</link>
		<comments>http://shokai.org/blog/archives/1270#comments</comments>
		<pubDate>Fri, 02 Mar 2007 07:47:31 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[C言語]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1270</guid>
		<description><![CDATA[最近出たこの本、すごくいい。 マイコンもATmega168で最新だし、gccでのコードが載っているのでよくわかる。 AVRマイコン活用ブック—オリジナル電子ゲーム&#038;ロボット製作 posted with amaz [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>最近出たこの本、すごくいい。<br /><br />
マイコンもATmega168で最新だし、gccでのコードが載っているのでよくわかる。</p>
<div class="amazlet-box" style="margin-bottom:0px;">
<div class="amazlet-image" style="float:left;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4885540011/shokai-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://images-jp.amazon.com/images/P/4885540011.09.MZZZZZZZ.jpg" alt="AVRマイコン活用ブック—オリジナル電子ゲーム&#038;ロボット製作" style="border: none;" /></a></div>
<div class="amazlet-info" style="float:left;margin-left:15px;line-height:120%">
<div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4885540011/shokai-22/ref=nosim/" name="amazletlink" target="_blank">AVRマイコン活用ブック—オリジナル電子ゲーム&#038;ロボット製作</a><br />
<div class="amazlet-powered-date" style="font-size:7pt;margin-top:5px;font-family:verdana;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/4885540011/shokai-22" title="AVRマイコン活用ブック—オリジナル電子ゲーム&#038;ロボット製作" target="_blank">amazlet</a> on 07.03.02</div>
</div>
<div class="amazlet-detail">松原 拓也 <br />電波新聞社 (1982/01)<br />売り上げランキング: 23347</div>
<div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4885540011/shokai-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div>
</div>
<div class="amazlet-footer" style="clear: left"></div>
</div>
<p>でもIOの操作で16進数とか使うのがあんまり好きじゃない。別にどう書いても動けばいいんだけど…<br /><br />
</p>
<blockquote><p>PORTB&nbsp;=&nbsp;0&#215;21;</p></blockquote>
<p>
<p>とか。0&#215;21、つまり10進数の33を代入しているので、PB5とPB0のピンを出力に設定しているという事だ。</p>
<p>でもこう書いたほうが好きだな。<br /><br />
</p>
<blockquote><p>PORTB&nbsp;=&nbsp;_BV(PB5)|_BV(PB0);</p></blockquote>
<p>
<p>それかアセンブラ風にこういうのも好き。<br /><br />
</p>
<blockquote><p>sbi(PORTB,PB5);<br />
sbi(PORTB,PB0);</p></blockquote>
<p>
<p>こういう書き方の方が16進数慣れてない人には見やすい。ピン配置とプログラムをある程度柔軟に変えやすいのが近代的。（PB0からPB3に変えるのも、エディタの置換で一発だ）</p>
<p>どうなってるのかというと……</p>
<p><span id="more-1270"></span><br /><br />
■PB5やPB0とは何か？<br /><br />
C:\WinAVR\avr\include\avr\iom8.h を見ると</p>
</p>
<blockquote><p>/*&nbsp;PORTB&nbsp;*/<br />
#define&nbsp;PB7&nbsp;&nbsp;7<br />
#define&nbsp;PB6&nbsp;&nbsp;6<br />
#define&nbsp;PB5&nbsp;&nbsp;5<br />
#define&nbsp;PB4&nbsp;&nbsp;4<br />
#define&nbsp;PB3&nbsp;&nbsp;3<br />
#define&nbsp;PB2&nbsp;&nbsp;2<br />
#define&nbsp;PB1&nbsp;&nbsp;1<br />
#define&nbsp;PB0&nbsp;&nbsp;0</p></blockquote>
<p>
と宣言されている。なので<br /><br />
</p>
<blockquote><p>PORTB = _BV(PB5)|_BV(PB0);</p></blockquote>
<p>
<p>は<br /><br />
</p>
<blockquote><p>PORTB = _BV(5)|_BV(0);</p></blockquote>
<p>
<p>と同じ事。</p>
<p>■_BV()とは何か？<br /><br />
C:\WinAVR\avr\include\avr\sfr_defs.h を見ると<br /><br />
</p>
<blockquote><p>#define&nbsp;_BV(bit)&nbsp;(1&nbsp;&lt;&lt;&nbsp;(bit))</p></blockquote>
<p>
<p>となっている。</p>
</p>
<blockquote><p>PORTB&nbsp;=&nbsp;_BV(5)|_BV(0);</p></blockquote>
<p>
<p>は<br /><br />
</p>
<blockquote><p>PORTB&nbsp;=&nbsp;1&lt;&lt;5|1&lt;&lt;0;</p></blockquote>
<p>
<p>となる。<br /><br />
つまり、_BVはn+1桁目のビットだけがセットされた数を返すマクロだ。</p>
<p>■論理和<br /><br />
最後に | は、両辺のビットの論理和をとるので</p>
</p>
<blockquote><p>0b100|0b001&nbsp;==&nbsp;0b101;</p></blockquote>
<p>
<p>になる。<br /><br />
というわけで_BVを使うのがわかりやすい。</p>
<p>■sbi, cbi<br /><br />
sbiとcbiをマクロで定義しておくと、レジスタ操作はアセンブラ風に書けて、ルーチンはC言語で書ける。<br /><br />
</p>
<blockquote><p>#define&nbsp;sbi(BYTE,BIT)&nbsp;BYTE|=_BV(BIT)<br />
#define&nbsp;cbi(BYTE,BIT)&nbsp;BYTE&amp;=~_BV(BIT)</p></blockquote>
<p>
<p>こんな風に。<br /><br />
</p>
<blockquote><p>sbi(PORTB,PB5);<br />
sbi(PORTB,PB0);</p></blockquote>
<p>
<p>■関連：<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/08/avrgcc.html">s.h.log: AVR-GCCのレジスタ操作関数&#038;マクロ</a></p>
</p>
<blockquote><p>loop_until_bit_is_set(UCSRA,UDRE);</p></blockquote>
<p>
<p>とか<br /><br />
</p>
<blockquote><p>if(bit_is_set(PINC,&nbsp;PC0))&nbsp;return&nbsp;0;<br />
if(bit_is_set(PINC,&nbsp;PC1))&nbsp;return&nbsp;1;<br />
if(bit_is_set(PINC,&nbsp;PC2))&nbsp;return&nbsp;2;<br />
if(bit_is_set(PINC,&nbsp;PC3))&nbsp;return&nbsp;3;<br />
if(bit_is_set(PINC,&nbsp;PC4))&nbsp;return&nbsp;4;<br />
if(bit_is_set(PINC,&nbsp;PC5))&nbsp;return&nbsp;5;</p></blockquote>
<p>
<p>とかもある。</p>
<p>そろそろ自分のlibcを整備しようかな</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1270/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>トランジスタでUARTを分岐させる</title>
		<link>http://shokai.org/blog/archives/1214</link>
		<comments>http://shokai.org/blog/archives/1214#comments</comments>
		<pubDate>Tue, 09 Jan 2007 11:52:02 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[UART]]></category>
		<category><![CDATA[トランジスタ]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1214</guid>
		<description><![CDATA[普段使う20ピンや28ピンのAVRには、UARTピンが1組しかない。64ピンとかになれば2組とか付いているけど。 んで昨日からDontronicsのUARTかUSBで制御できる小型LCDをいじっているんだけど、いつもシリ [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>普段使う20ピンや28ピンのAVRには、UARTピンが1組しかない。64ピンとかになれば2組とか付いているけど。</p>
<p>んで昨日からDontronicsのUARTかUSBで制御できる小型LCDを<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2007/01/dontronics-ulcd-color-sb.html">いじっている</a>んだけど、いつもシリアル通信でデバッグしているのに、UARTがLCDに占有されているせいでデバッグができない。</p>
<p>仕方ないので、信号用のトランジスタ<a href="http://akizukidenshi.com/catalog/items2.php?q=%22I-00359%22">2SC1815</a>と10kΩの抵抗を使って、UARTセレクタ（分岐させる回路）を作った。</p>
<p><a href="http://www.flickr.com/photos/shokai/351576814/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/162/351576814_1001d66fda_m.jpg" width="240" height="180" alt="usart selector" /></a><a href="http://www.flickr.com/photos/shokai/351577698/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/146/351577698_3e36c8179d_m.jpg" width="240" height="180" alt="usart selector" /></a></p>
<p><span id="more-1214"></span><br /><br />
■トランジスタで信号を分岐させる<br /><br />
<a href="http://www.flickr.com/photos/shokai/351589743/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/140/351589743_8e4aed70c8_o.gif" width="120" height="75" alt="transistor 2SC1815" /></a><a href="http://www.flickr.com/photos/shokai/351589770/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/70/351589770_c8a5d7c65d_o.gif" width="120" height="75" alt="transistor 2SC1815" /></a><br /><br />
ベースに電圧がかかっている間、コレクタからエミッタに電流が抜ける。<br /><br />
なので、マイコンのUARTのTXDを2つのトランジスタのコレクタ接続。エミッタをPCのシリアルポートに接続。マイコンのPD2,3はそれぞれのトランジスタのベースに接続する。<br /><br />
PD2,3のそれぞれ、電圧のかかっている方にシリアル通信が送られる。</p>
<p>■avr-gccでプログラム<br /><br />
main()の中でこうすると<br /><br />
<pre class="prettyprint">
for(;;){<br />
usart_selTxd(0);//出力ピン選択<br />
usart_sendStr(&qute;marutaka¥r¥n&qute;);<br />
usart_selTxd(1);<br />
usart_sendStr(&qute;zanmai¥r¥n&qute;);<br />
}<br />
</pre>
<p>こういう風に、別々のCOMポートに出力される。<br /><br />
<a href="http://www.flickr.com/photos/shokai/351550654/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/154/351550654_49f69d05a1_o.png" width="225" height="210" alt="usart selector" /></a></p>
<p>mainより先に宣言しておく関数。<br /><br />
<pre class="prettyprint">
/*TXDピンの出力先を選択する*/<br />
voidusart_selTxd(charn){<br />
loop_until_bit_is_set(UCSR0A,UDRE0);//送信データレジスタ空きまで待機<br />
switch(n){<br />
case0:<br />
cbi(PORTD,PD3);<br />
sbi(PORTD,PD2);<br />
break;<br />
case1:<br />
cbi(PORTD,PD2);<br />
sbi(PORTD,PD3);<br />
break;<br />
}<br />
}<br />
/*UARTで文字列送信*/<br />
voidusart_sendStr(char*str){<br />
while(*str!=NULL){<br />
loop_until_bit_is_set(UCSR0A,UDRE0);//送信データレジスタ空きまで待機<br />
UDR0=*str++;//1文字送信、1文字進む<br />
}<br />
}<br />
</pre>
<p>PD2,3のHIになっている方のCOMポートに出力される。<br /><br />
AVRのUARTは、UDRレジスタに書き込んだ後しばらくしてからTXDから送信される。UART専用のハードウェアで、物理的に別スレッドになっている。だからUDRに書き込む前にUCSRAのUDREビットをチェックして、UDRが空いているか確認しなければならない。</p>
<p>ところでATMega48からUDRやUCSRAが、UDR0やUCSR0Aとかに変わったんだけど、28ピンAVRでも2系統のUSARTが付くのだろうか？<br /><br />
今は名前があるだけで、UDR1やUCSR1Aはまだ無いな。</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1214/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dontronics uLCD128のカラーコード変換</title>
		<link>http://shokai.org/blog/archives/1211</link>
		<comments>http://shokai.org/blog/archives/1211#comments</comments>
		<pubDate>Mon, 08 Jan 2007 13:20:24 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[UART]]></category>
		<category><![CDATA[uLCD128]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1211</guid>
		<description><![CDATA[・Micro-LCD 届いたので使ってみた。 (hatayanlog) ・Dontronics :: 4d-Micro-LCD Old 畑山さんにもらったDontronicsの小型LCDを動かしてみた。シリアル通信で液晶 [...]]]></description>
			<content:encoded><![CDATA[<p>
・<a href="http://www.hatayan.org/weblog/archives/2006/01/07/111945.php">Micro-LCD 届いたので使ってみた。 (hatayanlog)</a><br />
・<a href="http://www.dontronics-shop.com/pages.php?pageid=56">Dontronics :: 4d-Micro-LCD Old</a><br />
畑山さんにもらったDontronicsの小型LCDを<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2007/01/lcd.html">動かしてみた</a>。シリアル通信で液晶画面を制御できる。<br />
uLCDの仕様では、色をrrrrrggggggbbbbbの計16bit(2byte)で赤緑青を表すようになっているので、2byteをmsb,lsbというそれぞれ1byteのデータに分け、シリアル通信で別々に送らなければならない。<br />
緑が丁度真ん中で割られてしまう。しかもなぜか緑だけ6byte。<br />
んでカラーコードの扱いが面倒臭かったので変換するコードを書いた（まだ試してない）<br />
→<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2007/01/dontronics-ulcd128-rgb.html">試した。やっぱりちょっと間違っていた。</a><br />
変換用関数(avr-gcc)<br />
<pre class="prettyprint">
char*colorToSb(char*color){<br />
charsb[2];<br />
//msb<br />
sb[0]=(color[0]&amp;0b11111)&lt;&lt;3//RED<br />
+(color[1]&amp;0b111000)&gt;&gt;3;//GREEN-A<br />
//lsb<br />
sb[1]=(color[1]&amp;0b111)&lt;&lt;3//GREEN-B<br />
+(color[2]&amp;0b11111);//BLUE;<br />
returnsb;<br />
}<br />
</pre>
mainからはこう呼ぶ<br />
<pre class="prettyprint">
charcolor[3]={0xFF,0xFF,0xFF};//RGB<br />
char*sb;<br />
sb=colorToSb(color);//msb,lsb取得<br />
//msb=sb[0],lsb=sb[1]<br />
</pre>
RGBで分けて書けて良い感じ。（明日実機で試す）<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1211/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3軸加速度センサ KXM52を使って傾斜を測定</title>
		<link>http://shokai.org/blog/archives/1198</link>
		<comments>http://shokai.org/blog/archives/1198#comments</comments>
		<pubDate>Thu, 28 Dec 2006 16:21:04 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[KXM52]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[加速度センサ]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1198</guid>
		<description><![CDATA[半年前にACA302という加速度センサを試したが、秋月電子で手に入らなくなった（取り扱い品がACA302からACB302になった）ので、樹に薦められたKXM52-1050モジュールを試してみた。 ACA302は3.3Vを [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>半年前に<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/06/aca302.html">ACA302という加速度センサを試した</a>が、秋月電子で手に入らなくなった（取り扱い品がAC<strong>A</strong>302から<a href="http://akizukidenshi.com/catalog/items2.php?q=%22I-00615%22">ACB302になった</a>）ので、樹に薦められた<a href="http://akizukidenshi.com/catalog/items2.php?q=%22I-01425%22">KXM52-1050モジュール</a>を試してみた。</p>
<p>ACA302は3.3Vを作らなければならなかったが、KXM52の動作電圧は2.7～5.5Vそのままで動くし、ノイズも全然無いのに<a href="http://herald.jugem.jp/?eid=79">ACB302より200円安く、感度も6倍</a>でいい感じ。<a href="http://www.ok.sfc.keio.ac.jp/pileus/">Pileus</a>2号機に採用する予定。<br /><br />
そういえば最近ACB302は2000円から1000円に値下げになったけどね</p>
<p>■とりあえず動かしてみた<br /><br />
<a href="http://shokai.org/archive/avr/mega168/061228_kxm52/">SourceCode, hex, Makefile(avr-gcc 3.4.6)</a><br /><br />
ATmega168のADC0,1,2でX,Y,Z軸の出力値をAD変換し、文字列に変換してUARTでPCに送っている。<br /><br />
<object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/ErfzjEQoxiI"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/ErfzjEQoxiI" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object><br /><br />
x,y軸の値は通常520ぐらいで、傾けると730～300ぐらいの間で変わる。これは重力加速度を検出しているということ</p>
<p><span id="more-1198"></span><br /><br />
普段の値<br /><br />
<a href="http://www.flickr.com/photos/shokai/336262470/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/125/336262470_8fd59df442_o.png" width="264" height="252" alt="Test of KXM52-1050 module" /></a></p>
<p>傾けた時<br /><br />
<a href="http://www.flickr.com/photos/shokai/336271478/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/134/336271478_3490dd3083_o.png" width="264" height="250" alt="Test of KXM52-1050 module" /></a></p>
<p>あとYouTubeに他の人が使ってるのもアップされてた。クワクボリョウタさんのI/O ToolkitとProce55ingを使ってる。<br /><br />
<object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/fphD41_g9fU"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/fphD41_g9fU" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object></p>
<p>■回路<br /><br />
付属のデータシートの通りにやった。<br /><br />
<a href="http://www.flickr.com/photos/shokai/336328843/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/157/336328843_2f11bffdae.jpg" width="500" height="375" alt="KXM52-1050 Accelerometer &#038; ATmega168" /></a><br /><br />
「KXM52-1050モジュール」なので、チップが基盤に既にはんだづけされていてそこにコンデンサなど全部実装されている。1,2ピンにVCCを、3,5ピンにGNDを接続すれば、6,7,8ピンがそれぞれX,Y,Z軸として加速度を出力してくれる。Xout,Yout,ZoutをATmega168のADC0,1,2にそのまま接続する。</p>
<p>■プログラム<br /><br />
<a href="http://shokai.org/archive/avr/mega168/061228_kxm52/">SourceCode, hex, Makefile(avr-gcc 3.4.6)</a><br /><br />
mainの中のforループで、ADC0,1,2の値を取って読みやすい文字列にしてUARTでPCに送っている。それだけ。<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/06/aca302.html">ACA302の時</a>の様に100回の平均を取る事はしないでも実用的な値が出た。</p>
<pre class="prettyprint">
int&nbsp;main(void){<br />
&nbsp;&nbsp;port_init();&nbsp;//&nbsp;PORT設定<br />
&nbsp;&nbsp;usart_init(MYUBRR);&nbsp;//&nbsp;USART設定<br />
&nbsp;&nbsp;adc_init();&nbsp;//&nbsp;ADConverter設定<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;LED_SET();&nbsp;//&nbsp;起動確認LED<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int&nbsp;adX,&nbsp;adY,&nbsp;adZ;<br />
&nbsp;&nbsp;char&nbsp;buf[6];<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;for(;;){<br />
&nbsp;&nbsp;&nbsp;&nbsp;adX&nbsp;=&nbsp;adc_convert(0);&nbsp;//&nbsp;ADC0からAD変換<br />
&nbsp;&nbsp;&nbsp;&nbsp;adY&nbsp;=&nbsp;adc_convert(1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;adZ&nbsp;=&nbsp;adc_convert(2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("x:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(intToStr(adX,buf));&nbsp;//&nbsp;AD値を文字列にして送信<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("&nbsp;y:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(intToStr(adY,buf));<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("&nbsp;z:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(intToStr(adZ,buf));<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("\r\n");&nbsp;//&nbsp;改行<br />
&nbsp;&nbsp;}<br />
}<br />
</pre>
<p>プログラム全体<br /><br />
<pre class="prettyprint">
#include&nbsp;&lt;avr/io.h&gt;<br />
#include&nbsp;&lt;avr/interrupt.h&gt;<br />
#define&nbsp;TRUE&nbsp;1<br />
#define&nbsp;FALSE&nbsp;0<br />
#define&nbsp;NULL&nbsp;'\0'<br />
#define&nbsp;sbi(BYTE,BIT)&nbsp;BYTE|=_BV(BIT)&nbsp;//&nbsp;BYTEの指定BITに1をセット<br />
#define&nbsp;cbi(BYTE,BIT)&nbsp;BYTE&amp;=~_BV(BIT)&nbsp;//&nbsp;BYTEの指定BITをクリア<br />
/**&nbsp;動作設定&nbsp;**/<br />
#define&nbsp;FOSC&nbsp;8000000&nbsp;//&nbsp;8MHz<br />
/**&nbsp;UART設定&nbsp;**/<br />
#define&nbsp;BAUD&nbsp;9600&nbsp;//&nbsp;9600bps<br />
#define&nbsp;MYUBRR&nbsp;FOSC/16/BAUD-1&nbsp;//&nbsp;UART分周率<br />
//&nbsp;#define&nbsp;UCSR0A_U2X0&nbsp;1&nbsp;//&nbsp;倍速フラグ&nbsp;等速ならコメントアウト<br />
#ifdef&nbsp;UCSR0A_U2X0&nbsp;//&nbsp;倍速が定義されているならば<br />
&nbsp;#define&nbsp;MYUBRR&nbsp;FOSC/16/(BAUD/2)-1&nbsp;//&nbsp;UART分周率(倍速)<br />
#endif<br />
volatile&nbsp;char&nbsp;usart_recvData;&nbsp;//&nbsp;USARTで受信したデータ<br />
#define&nbsp;LED_SET()&nbsp;sbi(PORTB,&nbsp;PB0)&nbsp;//&nbsp;基盤上の動作確認LED<br />
#define&nbsp;LED_CLR()&nbsp;cbi(PORTB,&nbsp;PB0)<br />
/*&nbsp;PORT設定&nbsp;*/<br />
void&nbsp;port_init(void){<br />
&nbsp;&nbsp;sbi(DDRB,&nbsp;PB0);<br />
}<br />
/*&nbsp;USART設定&nbsp;*/<br />
void&nbsp;usart_init(unsigned&nbsp;int&nbsp;ubrr){<br />
&nbsp;&nbsp;UBRR0H&nbsp;=&nbsp;(unsigned&nbsp;char)(ubrr&gt;&gt;8);&nbsp;//&nbsp;ボーレート上位8bit<br />
&nbsp;&nbsp;UBRR0L&nbsp;=&nbsp;(unsigned&nbsp;char)ubrr;&nbsp;//&nbsp;ボーレート下位8bit<br />
&nbsp;&nbsp;UCSR0A&nbsp;=&nbsp;(0&lt;&lt;U2X0);&nbsp;//&nbsp;等速<br />
&nbsp;&nbsp;UCSR0B&nbsp;=&nbsp;(1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0)|(1&lt;&lt;RXCIE0);&nbsp;//&nbsp;送受信許可、受信完了割り込み許可<br />
&nbsp;&nbsp;UCSR0C&nbsp;=&nbsp;(0&lt;&lt;UMSEL00)|(3&lt;&lt;UCSZ00)|(1&lt;&lt;USBS0)|(0&lt;&lt;UPM00);<br />
&nbsp;&nbsp;//&nbsp;フレーム設定&nbsp;非同期通信&nbsp;8ビット&nbsp;1ストップビット&nbsp;パリティ無し<br />
}<br />
/*&nbsp;intの桁数を返す&nbsp;*/<br />
char&nbsp;getDigit(int&nbsp;n){<br />
&nbsp;&nbsp;char&nbsp;i;<br />
&nbsp;&nbsp;i&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;while(n&gt;0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;/=&nbsp;10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;i++;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return&nbsp;i;<br />
}<br />
/*&nbsp;int-&gt;String変換&nbsp;*/<br />
char&nbsp;*intToStr(int&nbsp;n,&nbsp;char&nbsp;*buf){&nbsp;//&nbsp;変換する数、作業領域<br />
&nbsp;&nbsp;int&nbsp;i,&nbsp;digit;<br />
&nbsp;&nbsp;digit&nbsp;=&nbsp;getDigit(n);&nbsp;//&nbsp;桁数<br />
&nbsp;&nbsp;for(i&nbsp;=&nbsp;digit-1;&nbsp;i&nbsp;&gt;=&nbsp;0;&nbsp;i--){&nbsp;//&nbsp;intは最大5桁<br />
&nbsp;&nbsp;&nbsp;&nbsp;buf[i]&nbsp;=&nbsp;n%10+'0';<br />
&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;/=&nbsp;10;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;buf[digit]&nbsp;=&nbsp;'\0';&nbsp;//&nbsp;行末改行<br />
&nbsp;&nbsp;return&nbsp;buf;<br />
}<br />
/*&nbsp;UARTで文字列送信&nbsp;*/<br />
void&nbsp;usart_sendStr(char&nbsp;*str){<br />
&nbsp;&nbsp;while(*str&nbsp;!=&nbsp;NULL){<br />
&nbsp;&nbsp;&nbsp;&nbsp;loop_until_bit_is_set(UCSR0A,UDRE0);&nbsp;//&nbsp;送信データレジスタ空きまで待機<br />
&nbsp;&nbsp;&nbsp;&nbsp;UDR0&nbsp;=&nbsp;*str++;&nbsp;//&nbsp;1文字送信、1文字進む<br />
&nbsp;&nbsp;}<br />
}<br />
/*&nbsp;ADコンバータ設定&nbsp;*/<br />
void&nbsp;adc_init(void){<br />
&nbsp;&nbsp;ADMUX&nbsp;=&nbsp;(0&lt;&lt;REFS0);&nbsp;//&nbsp;外部基準電圧<br />
&nbsp;&nbsp;ADCSRA&nbsp;=(1&lt;&lt;ADEN)|(1&lt;&lt;ADSC)|(0&lt;&lt;ADPS0);<br />
&nbsp;&nbsp;//&nbsp;A/D変換許可、1回目変換開始(調整)、分周率2<br />
}<br />
/*&nbsp;ピンを指定してAD変換&nbsp;return&nbsp;0-1023&nbsp;*/<br />
int&nbsp;adc_convert(char&nbsp;pin){<br />
&nbsp;&nbsp;int&nbsp;ad;<br />
&nbsp;&nbsp;ADMUX&nbsp;=&nbsp;pin;&nbsp;//&nbsp;AD変換入力ピン<br />
&nbsp;&nbsp;cbi(ADCSRA,ADIF);<br />
&nbsp;&nbsp;sbi(ADCSRA,ADSC);&nbsp;//&nbsp;変換開始<br />
&nbsp;&nbsp;loop_until_bit_is_set(ADCSRA,ADIF);&nbsp;//&nbsp;変換完了まで待つ<br />
&nbsp;&nbsp;ad&nbsp;=&nbsp;ADCL;&nbsp;//&nbsp;下位8bit取得<br />
&nbsp;&nbsp;return&nbsp;ad&nbsp;+=&nbsp;(ADCH&lt;&lt;8);&nbsp;//&nbsp;上位2bit取得<br />
}<br />
int&nbsp;main(void){<br />
&nbsp;&nbsp;port_init();&nbsp;//&nbsp;PORT設定<br />
&nbsp;&nbsp;usart_init(MYUBRR);&nbsp;//&nbsp;USART設定<br />
&nbsp;&nbsp;adc_init();&nbsp;//&nbsp;ADConverter設定<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;LED_SET();&nbsp;//&nbsp;起動確認LED<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int&nbsp;adX,&nbsp;adY,&nbsp;adZ;<br />
&nbsp;&nbsp;char&nbsp;buf[6];<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;for(;;){<br />
&nbsp;&nbsp;&nbsp;&nbsp;adX&nbsp;=&nbsp;adc_convert(0);&nbsp;//&nbsp;ADC0からAD変換<br />
&nbsp;&nbsp;&nbsp;&nbsp;adY&nbsp;=&nbsp;adc_convert(1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;adZ&nbsp;=&nbsp;adc_convert(2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("x:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(intToStr(adX,buf));&nbsp;//&nbsp;AD値を文字列にして送信<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("&nbsp;y:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(intToStr(adY,buf));<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("&nbsp;z:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(intToStr(adZ,buf));<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr("\r\n");&nbsp;//&nbsp;改行<br />
&nbsp;&nbsp;}<br />
}<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1198/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATmega168でピン変化割り込み</title>
		<link>http://shokai.org/blog/archives/1190</link>
		<comments>http://shokai.org/blog/archives/1190#comments</comments>
		<pubDate>Sat, 23 Dec 2006 19:43:51 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1190</guid>
		<description><![CDATA[ATmega88以降は全てのI/Oピンに「外部入力割り込み」が付いている。これは、それぞれのピンに電流がONになったり、OFFになったりするとイベントが起こるという事だ。 今まではmain()の中のループで各ピンをずっと [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>ATmega88以降は全てのI/Oピンに「外部入力割り込み」が付いている。これは、それぞれのピンに電流がONになったり、OFFになったりするとイベントが起こるという事だ。</p>
<p>今まではmain()の中のループで各ピンをずっと監視し続けなければならなかったが、この外部入力ピンを使うと完全にイベントドリブンでプログラムを書ける様になる。ちなみにArduinoからは使えない機能です。<br /><br />
<a href="http://www.flickr.com/photos/shokai/331124001/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/159/331124001_f1b41deac8_m.jpg" width="240" height="180" alt="ATmega168 SIG_PIN_CHANGE0" /></a><a href="http://www.flickr.com/photos/shokai/331124340/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/127/331124340_6c037f16e4_m.jpg" width="240" height="180" alt="ATmega168 SIG_PIN_CHANGE0" /></a><br /><br />
■作った<br /><br />
PB1につながったスイッチを押した時に割り込み(SIG_PIN_CHANGE0)が発生し、UARTでPCに通知する。PB0のLEDも光らせる。スイッチを離すとLEDを消し、UARTで通知する。<br /><br />
<a href="http://shokai.org/archive/avr/mega168/061224_sig_pin_change/">SourceCode, hex, Makefile(avr-gcc 3.4.6)<br /><br />
</a></p>
<p>■外部入力割り込みの仕組み<br /><br />
2箇所設定する必要がある。<br /><br />
１．「ピン変化割り込みレジスタ」でピン変化割り込みを許可する<br /><br />
２．入力割り込みを受け取るピンを「ピン変化割り込みマスクレジスタ」で指定する</p>
<p>ピン変化割り込み0,1,2(PCIE0,1,2)の3つがあり、それぞれPORTB,PORTC,PORTDに対応している。<br /><br />
つまり、割り込み1つで7～8個のピンを受け持つという所が<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/07/avr_mega8.html">INT0,INT1の外部入力割り込み</a>と違う。</p>
<p><a href="http://reef.path.ne.jp/~hero/hero.htm">ATmega88のデータシート</a>の41ページを見るとPCICRというレジスタのPCIE0ビットに1をセットしてやるとピン変化割り込み0が許可される事がわかる。<br /><br />
</p>
<blockquote><p>sbi(PCICR,PCIE0); // ピン変化割り込み0</p></p></blockquote>
<p>
<p><span id="more-1190"></span><br /><br />
さらに、ピン変化割り込みマスクレジスタで、PCINT1(PB1)だけに反応する様に指定する。<br /><br />
</p>
<blockquote><p>PCMSK0&nbsp;=&nbsp;(1&lt;&lt;PCINT1);&nbsp;//&nbsp;PCINT1のみ許可</p></blockquote>
<p>
<p>PCINT0,1,2,3を許可する時はこうする<br /><br />
</p>
<blockquote><p>PCMSK0&nbsp;=&nbsp;(1&lt;&lt;PCINT0)|(1&lt;&lt;PCINT1)|(1&lt;&lt;PCINT2)|(1&lt;&lt;PCINT3);</p></blockquote>
<p>
<p>あとはmain()の中でsei()して、main()の後ろに外部割り込み0を受け取る関数 SIGNAL(SIG_PIN_CHANGE0) を宣言すれば割り込みが受け取れる。<br /><br />
SIG_PIN_CHANGEの中で実際どのピンが変化したのか判定しないとならないのがめんどいな…まあ変数で覚えておけばいいんだが</p>
</p>
<blockquote><p>
/**外部割り込み0**/<br />
SIGNAL(SIG_PIN_CHANGE0){<br />
&nbsp;&nbsp;if(bit_is_set(PINB, PB1)){&nbsp;//&nbsp;PB1立ち上がりの時<br />
&nbsp;&nbsp;&nbsp;&nbsp;LED_SET();&nbsp;//&nbsp;LED点灯<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(&quot;PB1_HIGH&yen;r&yen;n&quot;);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;LED_CLR();&nbsp;//&nbsp;LED消灯<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(&quot;PB1_LOW&yen;r&yen;n&quot;);<br />
&nbsp;&nbsp;}<br />
}<br />
</p></blockquote>
<p>
<p>ピン変化をシリアル通信で受信したスクリーンショット<br /><br />
<a href="http://www.flickr.com/photos/shokai/331155221/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/127/331155221_d6b2fadfdb_o.png" width="255" height="251" alt="ATmega168 SIG_PIN_CHANGE0" /></a></p>
<p>ちなみにSIGNAL()の中で指定する割り込みベクタ名は、<a href="http://reef.path.ne.jp/~hero/hero.htm">データシート</a>の33ページ「ATmega48/88/168の割り込みベクタ」の表のベクタ番号と、C:\WinAVR\avr\include\avr\iomx8.hの中で_VECTOR(番号)で#defineされている名前の組み合わせを見るとわかる。</p>
<p>今回のプログラムですよ<br /><br />
<br />
</p>
<blockquote><p>
#include&nbsp;&lt;avr/io.h&gt;<br />
#include&nbsp;&lt;avr/interrupt.h&gt;<br />
<br />
#define&nbsp;TRUE&nbsp;1<br />
#define&nbsp;FALSE&nbsp;0<br />
#define&nbsp;NULL&nbsp;&#8217;&yen;0&#8242;<br />
#define&nbsp;sbi(BYTE,BIT)&nbsp;BYTE|=_BV(BIT)&nbsp;//&nbsp;BYTEの指定BITに1をセット<br />
#define&nbsp;cbi(BYTE,BIT)&nbsp;BYTE&amp;=~_BV(BIT)&nbsp;//&nbsp;BYTEの指定BITをクリア<br />
<br />
/**&nbsp;動作設定&nbsp;**/<br />
#define&nbsp;FOSC&nbsp;8000000&nbsp;//&nbsp;8MHz<br />
<br />
/**&nbsp;UART設定&nbsp;**/<br />
#define&nbsp;BAUD&nbsp;9600&nbsp;//&nbsp;9600bps<br />
#define&nbsp;MYUBRR&nbsp;FOSC/16/BAUD-1&nbsp;//&nbsp;UART分周率<br />
//&nbsp;#define&nbsp;UCSR0A_U2X0&nbsp;1&nbsp;//&nbsp;倍速フラグ&nbsp;等速ならコメントアウト<br />
#ifdef&nbsp;UCSR0A_U2X0&nbsp;//&nbsp;倍速が定義されているならば<br />
&nbsp;#define&nbsp;MYUBRR&nbsp;FOSC/16/(BAUD/2)-1&nbsp;//&nbsp;UART分周率(倍速)<br />
#endif<br />
volatile&nbsp;char&nbsp;usart_recvData;&nbsp;//&nbsp;USARTで受信したデータ<br />
<br />
#define&nbsp;LED_SET()&nbsp;sbi(PORTB,&nbsp;PB0)&nbsp;//&nbsp;基盤上の動作確認LED<br />
#define&nbsp;LED_CLR()&nbsp;cbi(PORTB,&nbsp;PB0)<br />
<br />
<br />
/*&nbsp;PORT設定&nbsp;*/<br />
void&nbsp;port_init(void){<br />
&nbsp;&nbsp;sbi(DDRB,&nbsp;PB0);<br />
}<br />
<br />
<br />
/*&nbsp;USART設定&nbsp;*/<br />
void&nbsp;usart_init(unsigned&nbsp;int&nbsp;ubrr){<br />
&nbsp;&nbsp;UBRR0H&nbsp;=&nbsp;(unsigned&nbsp;char)(ubrr&gt;&gt;8);&nbsp;//&nbsp;ボーレート上位8bit<br />
&nbsp;&nbsp;UBRR0L&nbsp;=&nbsp;(unsigned&nbsp;char)ubrr;&nbsp;//&nbsp;ボーレート下位8bit<br />
&nbsp;&nbsp;UCSR0A&nbsp;=&nbsp;(0&lt;&lt;U2X0);&nbsp;//&nbsp;等速<br />
&nbsp;&nbsp;UCSR0B&nbsp;=&nbsp;(1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0)|(0&lt;&lt;RXCIE0);&nbsp;//&nbsp;送受信許可、受信完了割り込み不可<br />
&nbsp;&nbsp;UCSR0C&nbsp;=&nbsp;(0&lt;&lt;UMSEL00)|(3&lt;&lt;UCSZ00)|(1&lt;&lt;USBS0)|(0&lt;&lt;UPM00);<br />
&nbsp;&nbsp;//&nbsp;フレーム設定&nbsp;非同期通信&nbsp;8ビット&nbsp;1ストップビット&nbsp;パリティ無し<br />
}<br />
<br />
<br />
/*&nbsp;UARTで文字列送信&nbsp;*/<br />
void&nbsp;usart_sendStr(char&nbsp;*str){<br />
&nbsp;&nbsp;while(*str&nbsp;!=&nbsp;NULL){<br />
&nbsp;&nbsp;&nbsp;&nbsp;loop_until_bit_is_set(UCSR0A,UDRE0);&nbsp;//&nbsp;送信データレジスタ空きまで待機<br />
&nbsp;&nbsp;&nbsp;&nbsp;UDR0&nbsp;=&nbsp;*str++;&nbsp;//&nbsp;1文字送信、1文字進む<br />
&nbsp;&nbsp;}<br />
}<br />
<br />
/*&nbsp;ピン変化割り込み設定&nbsp;*/<br />
void&nbsp;pinchange_init(void){<br />
&nbsp;&nbsp;sbi(PCICR,&nbsp;PCIE0);&nbsp;//&nbsp;ピン変化割り込み0許可<br />
&nbsp;&nbsp;PCMSK0&nbsp;=&nbsp;(1&lt;&lt;PCINT1);&nbsp;//&nbsp;PCINT1のみ許可<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//&nbsp;sbi(PCICR,&nbsp;PCIE1);&nbsp;//&nbsp;ピン変化割り込み1許可<br />
&nbsp;&nbsp;//&nbsp;PCMSK1&nbsp;=&nbsp;(1&lt;&lt;PCINT8)|(1&lt;&lt;PCINT14);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//&nbsp;sbi(PCICR,&nbsp;PCIE2);&nbsp;//&nbsp;ピン変化割り込み2許可<br />
&nbsp;&nbsp;//&nbsp;PCMSK2&nbsp;=&nbsp;(1&lt;&lt;PCINT16)|(PCINT23);<br />
}<br />
<br />
<br />
int&nbsp;main(void){<br />
&nbsp;&nbsp;port_init();&nbsp;//&nbsp;PORT設定<br />
&nbsp;&nbsp;usart_init(MYUBRR);&nbsp;//&nbsp;USART設定<br />
&nbsp;&nbsp;pinchange_init();&nbsp;//&nbsp;ピン変化割り込み設定<br />
&nbsp;&nbsp;sei();&nbsp;//&nbsp;全割り込み許可<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;LED_SET();&nbsp;//&nbsp;起動確認LED<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;for(;;){<br />
&nbsp;&nbsp;}<br />
}<br />
<br />
<br />
/**&nbsp;外部割り込み0&nbsp;**/<br />
SIGNAL(SIG_PIN_CHANGE0){<br />
&nbsp;&nbsp;if(bit_is_set(PINB,&nbsp;PB1)){&nbsp;//&nbsp;PB1立ち上がりの時<br />
&nbsp;&nbsp;&nbsp;&nbsp;LED_SET();&nbsp;//&nbsp;LED点灯<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(&quot;PB1_HIGH&yen;r&yen;n&quot;);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;LED_CLR();&nbsp;//&nbsp;LED消灯<br />
&nbsp;&nbsp;&nbsp;&nbsp;usart_sendStr(&quot;PB1_LOW&yen;r&yen;n&quot;);<br />
&nbsp;&nbsp;}<br />
}<br />
</p></blockquote>
<p>
<br />
<p><a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/07/avr_atmega8.html">ロータリーエンコーダ</a>もタイマじゃなくピン変化割り込みでできそうだな。</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1190/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATmega168でAD変換</title>
		<link>http://shokai.org/blog/archives/1189</link>
		<comments>http://shokai.org/blog/archives/1189#comments</comments>
		<pubDate>Sat, 23 Dec 2006 17:17:22 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1189</guid>
		<description><![CDATA[ATmega168でADコンバータも試した。 CdS（光量センサ）と10kΩの抵抗を使った。 ADC0でAD変換した値を文字列に変換して、UARTでPCに送る ADC0の値が700以上の時、LEDを点灯させる。700以下 [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>ATmega168でADコンバータも試した。</p>
<p>CdS（光量センサ）と10kΩの抵抗を使った。<br /><br />
<a href="http://www.flickr.com/photos/shokai/330983737/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/128/330983737_9591d91a1a.jpg" width="500" height="375" alt="ATmega168 ADC and UART" /></a><br /><br />
ADC0でAD変換した値を文字列に変換して、UARTでPCに送る<br /><br />
ADC0の値が700以上の時、LEDを点灯させる。700以下だったら消灯する。</p>
<p>動いているところ<br /><br />
<object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/ynib66Vi2SY"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/ynib66Vi2SY" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object></p>
<p>■コード<br /><br />
<a href="http://shokai.org/archive/avr/mega168/061224_adc/">SourceCode, hex, Makefile(avr-gcc 3.4.6)</a></p>
<p>AD変換の準備のadc_init()、実際にAD変換を行ない値（int）を取るadc_convert(int pin)、USARTで文字列を送る関数 usart_sendStr()、intをStringに変換するintToStr(int, buf)を作った。</p>
<p><a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/10/arduino-uart-led-adc.html">s.h.log: Arduino &#8211; UART、LED、AD変換を試した</a>でも書いたが</p>
</p>
<blockquote><p><p>シリアル通信で送信できるのは8bitまで。AD値は10bit。<br /><br />
なので、そのままSerial.print()してしまうと上位2bitが飛んで変な値になる。</p>
<p>こういう時は<br /><br />
・上位2bit/下位8bitを2回に分けて送信し、PC側で連結する<br /><br />
・マイコン側で、AD値が0～50の時は&#8217;a'を送る／51～100の時は&#8217;b'を送るの様に、プロトコルを決める<br /><br />
・Stringにして送信して、PC側で数値に直す<br /><br />
・4で割ると、10bitの最大値1023が8bitの最大値255に納まる。ただし精度は4分の1になる<br /><br />
のどれかで対処する。</p></p></blockquote>
<p>
<p>なので今回は文字列に変換して送ってみた。これが無いとデバッグとかやってられない。</p>
<p><span id="more-1189"></span><br /><br />
今回のコード。</p>
<br />
<pre class="prettyprint">
#include &lt;avr/io.h&gt;<br />
#include &lt;avr/interrupt.h&gt;<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
#define NULL '\0'<br />
#define sbi(BYTE,BIT) BYTE|=_BV(BIT) // BYTEの指定BITに1をセット<br />
#define cbi(BYTE,BIT) BYTE&amp;=~_BV(BIT) // BYTEの指定BITをクリア<br />
<br />
/** 動作設定 **/<br />
#define FOSC 8000000 // 8MHz<br />
<br />
/** UART設定 **/<br />
#define BAUD 9600 // 9600bps<br />
#define MYUBRR FOSC/16/BAUD-1 // UART分周率<br />
// #define UCSR0A_U2X0 1 // 倍速フラグ 等速ならコメントアウト<br />
#ifdef UCSR0A_U2X0 // 倍速が定義されているならば<br />
 #define MYUBRR FOSC/16/(BAUD/2)-1 // UART分周率(倍速)<br />
#endif<br />
volatile char usart_recvData; // USARTで受信したデータ<br />
<br />
#define LED_SET() sbi(PORTB, PB0) // 基盤上の動作確認LED<br />
#define LED_CLR() cbi(PORTB, PB0)<br />
<br />
<br />
/* PORT設定 */<br />
void port_init(void){<br />
  sbi(DDRB, PB0);<br />
}<br />
<br />
<br />
/* USART設定 */<br />
void usart_init(unsigned int ubrr){<br />
  UBRR0H = (unsigned char)(ubrr&gt;&gt;8); // ボーレート上位8bit<br />
  UBRR0L = (unsigned char)ubrr; // ボーレート下位8bit<br />
  UCSR0A = (0&lt;&lt;U2X0); // 等速<br />
  UCSR0B = (1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0)|(1&lt;&lt;RXCIE0); // 送受信許可、受信完了割り込み許可<br />
  UCSR0C = (0&lt;&lt;UMSEL00)|(3&lt;&lt;UCSZ00)|(1&lt;&lt;USBS0)|(0&lt;&lt;UPM00);<br />
  // フレーム設定 非同期通信 8ビット 1ストップビット パリティ無し<br />
}<br />
<br />
/* intの桁数を返す */<br />
char getDigit(int n){<br />
  char i;<br />
  i = 0;<br />
  while(n&gt;0){<br />
    n /= 10;<br />
    i++;<br />
  }<br />
  return i;<br />
}<br />
<br />
/* int-&gt;String変換 */<br />
char *intToStr(int n, char *buf){ // 変換する数、作業領域<br />
  int i, digit;<br />
  digit = getDigit(n); // 桁数<br />
  for(i = digit-1; i &gt;= 0; i--){ // intは最大5桁<br />
    buf[i] = n%10+'0';<br />
    n /= 10;<br />
  }<br />
  buf[digit] = '\0'; // 行末改行<br />
  return buf;<br />
}<br />
<br />
/* UARTで文字列送信 */<br />
void usart_sendStr(char *str){<br />
  while(*str != NULL){<br />
    loop_until_bit_is_set(UCSR0A,UDRE0); // 送信データレジスタ空きまで待機<br />
    UDR0 = *str++; // 1文字送信、1文字進む<br />
  }<br />
}<br />
<br />
/* ADコンバータ設定 */<br />
void adc_init(void){<br />
  ADMUX = (0&lt;&lt;REFS0); // 外部基準電圧<br />
  ADCSRA =(1&lt;&lt;ADEN)|(1&lt;&lt;ADSC)|(0&lt;&lt;ADPS0);<br />
  // A/D変換許可、1回目変換開始(調整)、分周率2<br />
}<br />
<br />
/* ピンを指定してAD変換 return 0-1023 */<br />
int adc_convert(char pin){<br />
  int ad;<br />
  ADMUX = pin; // AD変換入力ピン<br />
  cbi(ADCSRA,ADIF);<br />
  sbi(ADCSRA,ADSC); // 変換開始<br />
  loop_until_bit_is_set(ADCSRA,ADIF); // 変換完了まで待つ<br />
  ad = ADCL; // 下位8bit取得<br />
  return ad += (ADCH&lt;&lt;8); // 上位2bit取得<br />
}<br />
<br />
int main(void){<br />
  port_init(); // PORT設定<br />
  usart_init(MYUBRR); // USART設定<br />
  adc_init(); // ADConverter設定<br />
  <br />
  LED_SET(); // 起動確認LED<br />
  <br />
  int ad;<br />
  char buf[6];<br />
  <br />
  for(;;){<br />
    ad = adc_convert(0); // ADC0からAD変換<br />
    if(ad &gt; 700) LED_SET();<br />
    else LED_CLR();<br />
    usart_sendStr(intToStr(ad,buf)); // AD値を文字列にして送信<br />
    usart_sendStr("\r\n"); // 改行<br />
  }<br />
}<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1189/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATmega168でUSART受信割り込み、シリアルエコー</title>
		<link>http://shokai.org/blog/archives/1187</link>
		<comments>http://shokai.org/blog/archives/1187#comments</comments>
		<pubDate>Sat, 23 Dec 2006 14:24:53 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[UART]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1187</guid>
		<description><![CDATA[mega168でUART受信割り込みできた。 回路はmega8の時と同じ。 さっきできなかった理由は割り込みベクタ名が間違ってた為だった。 コンパイル結果をよく見ると SIGNAL(SIG_UART_RECV)の所でwa [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>mega168でUART受信割り込みできた。</p>
<p>回路はmega8の時と同じ。<br /><br />
<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/12/atmega168-usart-echo.html">さっきできなかった</a>理由は割り込みベクタ名が間違ってた為だった。</p>
<p>コンパイル結果をよく見ると SIGNAL(SIG_UART_RECV)の所でwarningが出ていたので、avr-gccのフォルダの中のコードをよく読んだらSIG_USART_RECVになっていた。<br /><br />
コンパイラのバージョンというわけではなく、<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/12/winavr20060421.html">ATmega8のコードではSIG_UART_RECVで通る</a>のでATmega168以降はSIG_USART_RECVに変わったみたいだ。</p>
<p>あとavr/signal.hは廃止されてavr/interrupt.hに統合される模様。</p>
<p>■関連記事<br /><br />
<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/07/avr_mega8uart_1.html">s.h.log: AVR &#8211; MEGA8のUART送受信</a><br /><br />
<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/11/avr-atmega8-usart-echo.html">s.h.log: AVR &#8211; ATMega8でUSARTエコー</a></p>
<p>■コード<br /><br />
<a href="http://shokai.org/archive/avr/mega168/061223_usart-interrupt-echo/">SourceCode, hex, Makefile(avr-gcc 3.4.6)</a></p>
<p><span id="more-1187"></span><br /><br />
UARTで受信した文字を割り込みで反応する。それをmainの中で送り返す。<br /><br />
受信した瞬間だけLEDが点灯し、送信し返したら消灯する。</p>
<pre class="prettyprint">
#include&lt;avr/io.h&gt;<br />
#include&lt;avr/interrupt.h&gt;<br />
#defineTRUE1<br />
#defineFALSE0<br />
#defineNULL'¥0'<br />
#definesbi(BYTE,BIT)BYTE|=_BV(BIT)//BYTEの指定BITに1をセット<br />
#definecbi(BYTE,BIT)BYTE&amp;=~_BV(BIT)//BYTEの指定BITをクリア<br />
/**動作設定**/<br />
#defineFOSC8000000//8MHz<br />
/**UART設定**/<br />
#defineBAUD9600//9600bps<br />
#defineMYUBRRFOSC/16/BAUD-1//UART分周率<br />
//#defineUCSR0A_U2X01//倍速フラグ等速ならコメントアウト<br />
#ifdefUCSR0A_U2X0//倍速が定義されているならば<br />
#defineMYUBRRFOSC/16/(BAUD/2)-1//UART分周率(倍速)<br />
#endif<br />
volatilecharusart_recvData;//USARTで受信したデータ<br />
#defineLED_SET()sbi(PORTB,PB0)//基盤上の動作確認LED<br />
#defineLED_CLR()cbi(PORTB,PB0)<br />
/*PORT設定*/<br />
voidport_init(void){<br />
sbi(DDRB,PB0);<br />
}<br />
/*USART設定*/<br />
voidusart_init(unsignedintubrr){<br />
UBRR0H=(unsignedchar)(ubrr&gt;&gt;8);//ボーレート上位8bit<br />
UBRR0L=(unsignedchar)ubrr;//ボーレート下位8bit<br />
UCSR0A=(0&lt;&lt;U2X0);//等速<br />
UCSR0B=(1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0)|(1&lt;&lt;RXCIE0);//送受信許可、受信完了割り込み許可<br />
UCSR0C=(0&lt;&lt;UMSEL00)|(3&lt;&lt;UCSZ00)|(1&lt;&lt;USBS0)|(0&lt;&lt;UPM00);<br />
//フレーム設定非同期通信8ビット1ストップビットパリティ無し<br />
}<br />
intmain(void){<br />
port_init();//PORT設定<br />
usart_init(MYUBRR);//USART設定<br />
sei();//全割り込み許可<br />
<br />
LED_SET();//起動確認LED<br />
<br />
for(;;){<br />
if(usart_recvData){//受信データがある時<br />
loop_until_bit_is_set(UCSR0A,UDRE0);//送信データレジスタ空きまで待機<br />
UDR0=usart_recvData;<br />
usart_recvData=NULL;<br />
LED_CLR();<br />
}<br />
}<br />
}<br />
/**UART受信割り込み**/<br />
SIGNAL(SIG_USART_RECV){<br />
LED_SET();<br />
if(bit_is_clear(UCSR0A,FE0)){//フレーミングエラーが無い時<br />
usart_recvData=UDR0;//受信データをグローバル変数に取得<br />
}<br />
}<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1187/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATmega168でシリアルエコー</title>
		<link>http://shokai.org/blog/archives/1186</link>
		<comments>http://shokai.org/blog/archives/1186#comments</comments>
		<pubDate>Sat, 23 Dec 2006 14:01:53 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[UART]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1186</guid>
		<description><![CDATA[8MHz駆動になったmega168で、UARTエコー。 シリアルコンソールで送信した値がそのまま帰ってくる。 ATMega8の時とは違って、受信割り込みに反応して返すのではなくmain()の中のループで受け取って返してい [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>8MHz駆動になったmega168で、UARTエコー。</p>
<p>シリアルコンソールで送信した値がそのまま帰ってくる。<br /><br />
<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/11/avr-atmega8-usart-echo.html">ATMega8の時</a>とは違って、受信割り込みに反応して返すのではなくmain()の中のループで受け取って返している。というか受信割り込みから復帰できないので。<br /><br />
今晩中に解決できるといいな…</p>
<p><a href="http://shokai.org/archive/avr/mega168/061223_usart-echo/">SourceCode, hex, Makefile(avr-gcc 3.4.6)</a></p>
<p><span id="more-1186"></span></p>
<pre class="prettyprint">
#include&lt;avr/io.h&gt;<br />
#include&lt;avr/interrupt.h&gt;<br />
#include&lt;avr/signal.h&gt;<br />
#defineTRUE1<br />
#defineFALSE0<br />
#defineNULL'¥0'<br />
#definesbi(BYTE,BIT)BYTE|=_BV(BIT)//BYTEの指定BITに1をセット<br />
#definecbi(BYTE,BIT)BYTE&amp;=~_BV(BIT)//BYTEの指定BITをクリア<br />
/**動作設定**/<br />
#defineFOSC8000000//8MHz<br />
/**UART設定**/<br />
#defineBAUD9600//9600bps<br />
#defineMYUBRRFOSC/16/BAUD-1//UART分周率<br />
//#defineUCSR0A_U2X01//倍速フラグ等速ならコメントアウト<br />
#ifdefUCSR0A_U2X0//倍速が定義されているならば<br />
#defineMYUBRRFOSC/16/(BAUD/2)-1//UART分周率(倍速)<br />
#endif<br />
volatilecharusart_recvData;//USART受信データ<br />
#defineLED_SET()sbi(PORTB,PB0)//基盤上の動作確認LED<br />
#defineLED_CLR()cbi(PORTB,PB0)<br />
/*PORT設定*/<br />
voidport_init(void){<br />
sbi(DDRB,PB0);<br />
}<br />
/*USART設定*/<br />
voidusart_init(unsignedintubrr){<br />
UBRR0H=(unsignedchar)(ubrr&gt;&gt;8);//ボーレート上位8bit<br />
UBRR0L=(unsignedchar)ubrr;//ボーレート下位8bit<br />
UCSR0A=(0&lt;&lt;U2X0);//等速<br />
UCSR0B=(1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0)|(0&lt;&lt;RXCIE0);//送受信許可、受信完了割り込み不許可<br />
UCSR0C=(0&lt;&lt;UMSEL00)|(3&lt;&lt;UCSZ00)|(1&lt;&lt;USBS0)|(0&lt;&lt;UPM00);<br />
//フレーム設定非同期通信8ビット1ストップビットパリティ無し<br />
}<br />
intmain(void){<br />
port_init();//PORT設定<br />
usart_init(MYUBRR);//USART設定<br />
<br />
LED_SET();//起動確認LED<br />
<br />
for(;;){<br />
if(bit_is_set(UCSR0A,RXC0)){//受信データがある時<br />
usart_recvData=UDR0;//受信データ読み出し<br />
loop_until_bit_is_set(UCSR0A,UDRE0);//送信レジスタ空きまで待機<br />
UDR0=usart_recvData;//送信データ書き込み<br />
}<br />
}<br />
}<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1186/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATmega168のクロックを内蔵8Mhzに切り替える</title>
		<link>http://shokai.org/blog/archives/1185</link>
		<comments>http://shokai.org/blog/archives/1185#comments</comments>
		<pubDate>Sat, 23 Dec 2006 09:51:46 +0000</pubDate>
		<dc:creator>moblog</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[ATMega168]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[avr-gcc]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shlog.sakura.ne.jp/blog/?p=1185</guid>
		<description><![CDATA[マルツで買ったATmega168に「avrsp -fl11100010」して、8Mhzで動かす設定に変えた。 最初は1MHzなのでこのままでは使い物にならないので、avrspを使ってヒューズビットのロービットを書き換えて [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>マルツで買ったATmega168に「avrsp -fl11100010」して、8Mhzで動かす設定に変えた。</p>
<p><a href="http://www.flickr.com/photos/shokai/315763899/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/112/315763899_043f74d7e1_m.jpg" width="240" height="180" alt="ATMega168" /></a><a href="http://www.flickr.com/photos/shokai/321360616/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/137/321360616_3cd63e5d79_m.jpg" width="240" height="180" alt="ATmega168 USART,LED" /></a></p>
<p><a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/12/atmega168-test.html"><br /><br />
最初は1MHz</a>なのでこのままでは使い物にならないので、<a href="http://elm-chan.org/works/avrx/report.html">avrsp</a>を使ってヒューズビットのロービットを書き換えて内蔵8MHzで動かす。mega8とはロービットが微妙に変わっているので、mega8そのままではできない。</p>
<p><span id="more-1185"></span><br /><br />
■avrspでロービットを書き換える<br /><br />
<a href="http://reef.path.ne.jp/~hero/hero.htm">HERO&#8217;S Download</a>のmega88（168と兼用）のデータシートの19ページより<br /><br />
<a href="http://www.flickr.com/photos/shokai/330757049/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/165/330757049_8fc6ac0824_o.png" width="248" height="65" alt="atmega168 clock" /></a><br /><br />
CKSEL3～0の指定で内蔵クロック動作になる事がわかった。<br /><br />
0010（左が3、右端が0）</p>
<p>また、179ページで下位バイトの一覧が見れる。<br /><br />
<a href="http://www.flickr.com/photos/shokai/330757443/" title="Photo Sharing"><img src="http://farm1.static.flickr.com/154/330757443_ef30cf1759.jpg" width="500" height="132" alt="atmega168 clock" /></a><br /><br />
出荷時の設定でCKSEL3～0が0010に既になっているが、CKDIV8のせいで8分周選択になっているので、内蔵8MHzが1MHz動作になっている事がわかる。<br /><br />
なのでCKDIVを1にして、8分周をやめさせる。別に1がTrue / 0がFlaseとかいう世界じゃないので、ちゃんとレジスタ表を読んで確認する。<br /><br />
下位バイト：11100010（左がCKDIV、右がCKSEL0）</p>
<p>実際に書き込む前に、念のためにコマンドプロンプトで<br /><br />
</p>
<blockquote><p>>avrsp-rf</p></p></blockquote>
<p>
<p>すると<br /><br />
</p>
<blockquote><p>Detected device is ATmega168.<br /><br />
Low: 01100010<br /><br />
High:11-11111<br /><br />
Ext: &#8212;&#8211;001<br /><br />
Cal: 148</p></p></blockquote>
<p>
<p>と出る。現在のヒューズビットの値がわかる。</p>
<p>下位ビットを書き換える<br /><br />
</p>
<blockquote><p>avrsp-fl11100010</p></p></blockquote>
<p>
<p>終わり。<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/12/atmega168-test.html">s.h.log: ATmega168を動かしてみた</a>のプログラムを8MHzに直して書き込んだら、ちゃんと9600bpsで通信できた。</p>
<p>■関連エントリ<br /><br />
・<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/04/avr_tiny2313uar.html">s.h.log: AVR &#8211; TINY2313のヒューズビット切り替え、UART</a><br /><br />
・<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/04/avr_mega8uart.html">s.h.log: AVR &#8211; MEGA8のヒューズビット切り替え、UART</a><br /><br />
・<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2005/07/atmega8.html">s.h.log: ATmega8を外部クリスタルで動かす</a><br /><br />
・<a href="http://web.sfc.keio.ac.jp/~shokai/archives/2006/12/atmega168-test.html">s.h.log: ATmega168を動かしてみた</a></p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1185/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

