Top > 12F629、12F675でシリアル通信

広告

12F629や12F675でシリアル通信

12F629や12F675のようにシリアル通信の機能「USART」が無い場合は自力でタイミングなどを設定する必要がある。

RS232Cの場合、ただ通信するだけなら送信、受信の2本線があれば良く、GNDと合わせても3本線で通信ができるので簡単。
そして通信する双方の通信速度、データビット長、パリティー、ストップビット長を合わせてあげれば通信できる。

必要な部品

コンデンサや抵抗以外には

  • 12F629や12F675
  • RS232C用のレベル変換IC
    • 秋月電子などに売っている「ADM3202」シリーズなど
  • D-subコネクタ
    • 秋月電子などに売っている

回路

シリアル通信用の簡単な回路は以下の図の通り、RS232C用のレベル変換ICとして「ADM3202」を使っている。
12F629、12F675どちらも同じ回路で大丈夫

12F675_serial.png

プリントパターンは以下の通り

12F675_serial_pcb.png

印刷用

アセンブラソース

以下のソースは12F675用。12F629用にするためには先頭の2行を変える。
内部クロックだとあまり精度が良くないためタイミングを作る待ちルーチンはチップごとに調整が必要。

送信

PICと温度計モジュールを利用した、温度計測装置の作成」のソースを改造した物。
「Test」という文字を送り続ける。
データビット長8bit、パリティーなし、ストップビット長1bitです。
通信速度が早くなってくるとタイミングを合わせるのが大変になってくる。
ターミナルソフトで受信して文字化けするようなら待ちタイミングを調整する必要がある。NOPの数を増減させて受信してみる。
まったく字すら出てこないようなら、送信・受信の接続が逆、そもそも壊れているなどが考えられる。PIC自体が壊れているときもあるので確認してみる。

; Test RS-232C
; GPIO 5 = TXD
; GPIO 3 = RXD
	list p=12f675	;12F629のときはここを変える
	include	p12f675.inc	;12F629のときはここを変える
	__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
	__IDLOCS	H'0100'
	CBLOCK	H'20'
	CNT1
	CNT3
	BUF
	ENDC
;ポートを定義
#DEFINE	TX232	GPIO,5	;GPIOレジスタの第5ビットを送信用にする
#DEFINE	RX232	GPIO,3	;GPIOレジスタの第3ビットを受信用にする
;----Initial setting
L1:
	BCF		STATUS,RP0 ;Bank 0
	CLRF		GPIO       ;Init GPIO
	MOVLW	07h        ;
	MOVWF	CMCON      ;digital IO
	BSF   	STATUS,RP0 ;Bank 1
	CLRF		ANSEL      ;Digital I/O
	MOVLW	B'00011111'        ;ポート4を出力、ポート0,1,2,3,4を入力に設定します。3 is read
	MOVWF 	TRISIO     ;
	BCF		STATUS,RP0 ;Bank 0
	BSF		TX232	;データを送信しないときは常に1を送出していなければならないので、GPIOレジスタの第5ビットを1にします。
;----SEND DATA
L2:
	MOVLW	A'T'
	CALL		SEND232C
	MOVLW	A'e'
	CALL		SEND232C
	MOVLW	A's'
	CALL		SEND232C
	MOVLW	A't'
	CALL		SEND232C
	MOVLW	0x0a		;Send LF
	CALL		SEND232C
	GOTO          L2
;--------RS232--------
;参考サイト
;http://scw.asahi-u.ac.jp/~sanozemi/Sakuhin/pic02/PIC02.html
SEND232C:	;Wレジスターより、送出すべき文字をBUFに受け取ります。続いて、スタートビットとして、とにかく、0を送出します。その後待ちます。
	MOVWF	BUF	;W -> BUF
	MOVLW	D'8'
	MOVWF	CNT3
	BCF		TX232	;0を送出
	CALL		W232
L9:
	;データを、下位ビットから順に8ビット送出します。
	BTFSS	BUF,0	;BUFの0ビット目が1なら次をスキップ
	BCF		TX232	;0を送出
	BTFSC	BUF,0	;BUFの0ビット目が0なら次をスキップ
	BSF		TX232	;1を送出
	CALL		W232		;Wait
	RRF		BUF,F	;シフト
	DECFSZ	CNT3,F
	GOTO		L9
	BSF		TX232	;最後に、ストップビットとして、1を送出します。
	CALL		W232
	RETURN
;---wait 10us	
W10
	MOVLW	D'2'
	MOVWF	CNT1
WL10
	DECFSZ	CNT1,F
	GOTO		WL10
	RETURN
;------------Wait------------
;19200bps=52us
;38400bps=26us
;57600bps=17us
;4MHz clock=> 1us/cycle
;細かに調整するためにループを使わないでやってみる。
;個体差があるのでそれぞれのチップで調整が必要
W232:	;38400bps用 NOPx14
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	RETURN
;19200bpsなら以下のループでも大丈夫
;W232:
;	MOVLW	D'14'	;19200bps
;	MOVWF	CNT1
;WWL:
;	DECFSZ	CNT1,F
;	GOTO		WWL
	END	;プログラムの最後

送信、受信

受信も含めたもの。一文字ずつループバックする。通信速度は38400bps、データビット長8bit、パリティーなし、ストップビット長1bitです。
受信部の元にさせて頂いたサイトを失念してしまいました。すみません。
通信速度が速くなってくると、処理する時間が少なくなってしまうためできるだけステップ数が少なくなるようにする必要があります。
もし不都合なら、通信速度を落とすか、内部クロックを使わずに外部発振子を使うようにします。
送信がOKなら受信のタイミングもOKなはず。受信ができないなら接続や回路、チップの故障を疑ってみる。
但し上にも書いたように立て続けに受信させようとすると処理が間に合わない場合がある。

	list p=12f675		;12F629のときはここを変える
	include	p12f675.inc	;12F629のときはここを変える
	__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
	__IDLOCS	H'0100'
	CBLOCK	H'20'
	CNT1
	CNT3
	BUF
	BITCNT
	RXDATA
	ENDC
;ポートを定義
#DEFINE	TX232	GPIO,5	;GPIOレジスタの第5ビットを送信用にする
#DEFINE	RX232	GPIO,3	;GPIOレジスタの第3ビットを受信用にする
;----Initial setting
L1:
	BCF		STATUS,RP0 ;Bank 0
	CLRF		GPIO       ;Init GPIO
	MOVLW	07h        ;
	MOVWF	CMCON      ;digital IO
	BSF   	STATUS,RP0 ;Bank 1
	CLRF		ANSEL      ;Digital I/O
	MOVLW	B'00011111'        ;ポート4を出力、ポート0,1,2,3,4を入力に設定します。3 is read
	MOVWF 	TRISIO     ;
	BCF		STATUS,RP0 ;Bank 0
	BSF		TX232	;データを送信しないときは常に1を送出していなければならないので、GPIOレジスタの第5ビットを1にします。

;----SEND DATA
L2:
	MOVLW	A'T'
	CALL		SEND232C
	MOVLW	A'e'
	CALL		SEND232C
	MOVLW	A's'
	CALL		SEND232C
	MOVLW	A't'
	CALL		SEND232C
	MOVLW	A'>'
	CALL		SEND232C
;----GET Command DATA
	CALL		RXSTART
;----Send recived Command
	MOVF		RXDATA,W
	CALL		SEND232C
	GOTO          L2
;----Recive Command DATA
RXSTART:
	MOVLW	D'8'		;Count set
	MOVWF	BITCNT
	CLRF		RXDATA		;Clear RXDATA
	BTFSC	RX232	;IF RX232 is Clear
	GOTO		RXSTART
	CALL		W10	;Wait 10us
	BTFSC	RX232	;IF RX232 is Clear
	GOTO		RXSTART
RXLOOP:
	CALL		W232		;wait
	BCF     STATUS,C    	;ビット0セット
	BTFSC   RX232   	;受信ビット0か1か
	BSF     STATUS,C    	;1 の時1にセット
	RRF     RXDATA,F     	;RXDATAに1ビット書き込み
	DECFSZ	BITCNT,F
	GOTO		RXLOOP
	RETURN
;--------RS232--------
;参考サイト
;http://scw.asahi-u.ac.jp/~sanozemi/Sakuhin/pic02/PIC02.html

SEND232C:	;Wレジスターより、送出すべき文字をBUFに受け取ります。続いて、スタートビットとして、とにかく、0を送出します。その後待ちます。
	MOVWF	BUF	;W -> BUF
	MOVLW	D'8'
	MOVWF	CNT3
	BCF		TX232	;0を送出
	CALL		W232
L9:
	;データを、下位ビットから順に8ビット送出します。
	BTFSS	BUF,0	;BUFの0ビット目が1なら次をスキップ
	BCF		TX232	;0を送出
	BTFSC	BUF,0	;BUFの0ビット目が0なら次をスキップ
	BSF		TX232	;1を送出
	CALL		W232		;Wait
	RRF		BUF,F	;シフト
	DECFSZ	CNT3,F
	GOTO		L9
	BSF		TX232	;最後に、ストップビットとして、1を送出します。
	CALL		W232
	RETURN
;---wait 10us	
W10
	MOVLW	D'3'		;要調整
	MOVWF	CNT1
WL10
	DECFSZ	CNT1,F
	GOTO		WL10
	RETURN
;------------Wait------------
;19200bps=52us
;38400bps=26us
;57600bps=17us
;4MHz clock=> 1us/cycle
;細かに調整するためにループを使わないでやってみる。
;個体差があるのでそれぞれのチップで調整が必要
W232:	;38400bps用 NOPx14
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	RETURN
;19200bpsなら以下のループでも大丈夫
;W232:
;	MOVLW	D'14'	;19200bps
;	MOVWF	CNT1
;WWL:
;	DECFSZ	CNT1,F
;	GOTO		WWL

	END	;プログラムの最後

広告

Attach file: file12F675_serial.png 2009 download [Information] file12F675_serial_pcb.png 785 download [Information] file12F675_serial_pcb.pdf.tgz 619 download [Information]

Reload   Diff   Front page List of pages Search Recent changes Backup Referer   Help   RSS of recent changes
Last-modified: Wed, 04 Jan 2012 23:12:15 HADT (3181d)