STM32F103のUSARTを送受信割込みで使ってみる [ARM&Cortex-M3]
つまり低水準入出力関数の更に下の階層ですな。
※一部のtx、rxのリマップに修正を加えています。
使い方
ヘッダーファイル
Cソース
stm32f10x_it.cの割込み処理のところ
※一部のtx、rxのリマップに修正を加えています。
使い方
void hoge( void ) { char SndBuf[ 128 ],RcvBuf[ 128 ]; SCI_BUFFER snd,rcv; snd.buf = SndBuf; snd.wptr = snd.rptr = 0; snd.size = sizeof(SndBuf); rcv.buf = RcvBuf; rcv.wptr = rcv.rptr = 0; rcv.size = sizeof(RcvBuf); (void)SCI_Init( SCI_1, &rcv, &snd, BAUD_115200 ); while( 1 ) { while( RcvSizeOfBuf( SCI_1 ) == 0 ) ; SCI_Putc( SCI_1, SCI_Getc( SCI_1 ) ); } }
ヘッダーファイル
/*************************************************************************/ /* STM32F103VBT6のUSARTを使う */ /* USART1はPA9,PA10、USART2はPD5,PD6、USART3はPD8,PD9に接続されている。 */ /* designed by hamayan since 2008/11/06 */ /*************************************************************************/ /*************************************************************************/ /* ボーレート定義 */ /*************************************************************************/ #define BAUD_230400 (0x00000271UL / 2) #define BAUD_115200 (0x00000271UL) #define BAUD_57600 (0x000004E2UL) #define BAUD_38400 (0x00000753UL) #define BAUD_19200 (0x00000EA6UL) #define BAUD_9600 (0x00001D4CUL) /*************************************************************************/ /* 端子定義 */ /*************************************************************************/ /*************************************************************************/ /* IOレジスタ定義 */ /*************************************************************************/ /*************************************************************************/ /* レジスタ bit定義 */ /*************************************************************************/ /*SR*/ #define PE_Bit 0x00000001 #define FE_Bit 0x00000002 #define NE_Bit 0x00000004 #define ORE_Bit 0x00000008 #define IDLE_Bit 0x00000010 #define RXNE_Bit 0x00000020 #define TC_Bit 0x00000040 #define TXE_Bit 0x00000080 #define LBD_Bit 0x00000100 #define CTS_Bit 0x00000200 /*CR1*/ #define SBK_Bit 0x00000001 #define RWU_Bit 0x00000002 #define RE_Bit 0x00000004 #define TE_Bit 0x00000008 #define IDLEIE_Bit 0x00000010 #define RXNEIE_Bit 0x00000020 #define TCIE_Bit 0x00000040 #define TXEIE_Bit 0x00000080 #define PEIE_Bit 0x00000100 #define PS_Bit 0x00000200 #define PCE_Bit 0x00000400 #define WAKE_Bit 0x00000800 #define M_Bit 0x00001000 #define UE_Bit 0x00002000 /*CR2*/ #define LBDL_Bit 0x00000020 #define LBDIE_Bit 0x00000040 #define LBCL_Bit 0x00000100 #define CPHA_Bit 0x00000200 #define CPOL_Bit 0x00000400 #define CLKEN_Bit 0x00000800 #define STOP0_Bit 0x00001000 #define STOP1_Bit 0x00002000 #define LINEN_Bit 0x00004000 /*CR3*/ #define EIE_Bit 0x00000001 #define IREN_Bit 0x00000002 #define IRLP_Bit 0x00000004 #define HDSEL_Bit 0x00000008 #define NACK_Bit 0x00000010 #define SCEN_Bit 0x00000020 #define DMAR_Bit 0x00000040 #define DMAT_Bit 0x00000080 #define RTSE_Bit 0x00000100 #define CTSE_Bit 0x00000200 #define CTSIE_Bit 0x00000400 /*************************************************************************/ /* その他の定義 */ /*************************************************************************/ typedef enum { SCI_1 = 0, SCI_2, SCI_3, SCI_4, SCI_5, } SciNum_t; typedef struct { unsigned long sr; unsigned long dr; unsigned long brr; unsigned long cr1; unsigned long cr2; unsigned long cr3; unsigned long gtpr; } SCI_REG; typedef struct { void *buf; unsigned short wptr,rptr; unsigned short size; } SCI_BUFFER; /*************************************************************************/ /* 大域変数宣言 */ /*************************************************************************/ /*************************************************************************/ /* プロトタイプ宣言 */ /*************************************************************************/ int SCI_Init( int ch, SCI_BUFFER *rcv, SCI_BUFFER *snd, unsigned long brr ); int SCI_Putc( int ch, char c ); int SCI_Puts( int ch, char *str ); int SCI_Getc( int ch ); unsigned short RcvSizeOfBuf( int ch ); unsigned short SndSizeOfBuf( int ch ); void SCI_ISR( int ch ); unsigned long SCI_Status( int ch ); char SCI_DirectRead( int ch ); /*************************************************************************/ /* end of file */ /* designed by hamayan since 2008/11/06 */ /*************************************************************************/
Cソース
/*************************************************************************/ /* STM32F103VBT6のUSARTを何とかする */ /* designed by hamayan since 2008/11/06 */ /*************************************************************************/ #include "stm32f10x_lib.h" //#include "delivertive.h" #include "usart.h" #define PA_CRH (GPIOA->CRH) #define PC_CRH (GPIOC->CRH) #define PD_CRL (GPIOD->CRL) #define PD_CRH (GPIOD->CRH) #define AFIO_MAPR (AFIO->MAPR) /*************************************************************************/ /* 端子定義 */ /*************************************************************************/ /*************************************************************************/ /* その他の定義 */ /*************************************************************************/ /*************************************************************************/ /* 大域変数宣言 */ /*************************************************************************/ static SCI_BUFFER *sci_snd[ 5 ]; static SCI_BUFFER *sci_rcv[ 5 ]; /*************************************************************************/ /* プロトタイプ宣言 */ /*************************************************************************/ static SCI_REG *Select_SCI( int ch ); /*************************************************************************/ /* SCI(USART)初期化 */ /*************************************************************************/ static SCI_REG *Select_SCI( int ch ) { switch ( ch ) { case SCI_1 : return (SCI_REG *)USART1; case SCI_2 : return (SCI_REG *)USART2; case SCI_3 : return (SCI_REG *)USART3; case SCI_4 : return (SCI_REG *)USART4; case SCI_5 : return (SCI_REG *)USART5; default : break; } return (SCI_REG *)0; } /*************************************************************************/ /* SCI(USART)初期化 */ /*************************************************************************/ int SCI_Init( int ch, SCI_BUFFER *rcv, SCI_BUFFER *snd, unsigned long brr ) { NVIC_InitTypeDef NVIC_InitStructure; SCI_REG *sci = Select_SCI( ch ); if( sci == (SCI_REG *)0 ) return (-1); sci_rcv[ ch ] = rcv; sci_snd[ ch ] = snd; switch ( ch ) { case SCI_1 : AFIO_MAPR &= 0xfffffffb; PA_CRH &= 0xfffff00f; /*pa9=tx,pa10=rx*/ PA_CRH |= 0x000004b0; /*USART1へクロックの供給開始*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE ); RCC_APB2PeriphResetCmd( RCC_APB2Periph_USART1, DISABLE ); /*USART1の割り込み設定*/ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel; break; case SCI_2 : AFIO_MAPR |= 0x00000008; /*pd5,6で使用するにはリマップが必要*/ PD_CRL &= 0xf00fffff; /*pd5=tx,pd6=rx*/ PD_CRL |= 0x04b00000; /*USART2へクロックの供給開始*/ RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE ); RCC_APB1PeriphResetCmd( RCC_APB1Periph_USART2, DISABLE ); /*USART2の割り込み設定*/ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel; brr /= 2; break; case SCI_3 : AFIO_MAPR &= 0xffffffcf; /*pd8,9で使用するにはリマップが必要*/ AFIO_MAPR |= 0x00000030; /*pd8,9で使用するにはリマップが必要*/ PD_CRH &= 0xffffff00; /*pd8=tx,pd9=rx*/ PD_CRH |= 0x0000004b; /*USART3へクロックの供給開始*/ RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE ); RCC_APB1PeriphResetCmd( RCC_APB1Periph_USART3, DISABLE ); /*USART3の割り込み設定*/ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel; brr /= 2; break; case SCI_4 : PC_CRH &= 0xffff00ff; /*pc10=tx,pc11=rx*/ PC_CRH |= 0x00004b00; /*USART4へクロックの供給開始*/ RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART4, ENABLE ); RCC_APB1PeriphResetCmd( RCC_APB1Periph_USART4, DISABLE ); /*USART4の割り込み設定*/ NVIC_InitStructure.NVIC_IRQChannel = USART4_IRQChannel; brr /= 2; break; case SCI_5 : PC_CRH &= 0xfff0ffff; /*pc12=tx*/ PC_CRH |= 0x000b0000; PD_CRL &= 0xfffff0ff; /*pd2=rx*/ PD_CRL |= 0x00000400; /*USART5へクロックの供給開始*/ RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART5, ENABLE ); RCC_APB1PeriphResetCmd( RCC_APB1Periph_USART5, DISABLE ); /*USART5の割り込み設定*/ NVIC_InitStructure.NVIC_IRQChannel = USART5_IRQChannel; brr /= 2; break; } sci->cr1 = 0; /*USART停止*/ sci->brr = brr; /*???bps*/ sci->cr2 = 0; /**/ sci->cr3 = EIE_Bit; /*エラー発生時の割り込み許可*/ sci->cr1 = UE_Bit | TE_Bit | RE_Bit | RXNEIE_Bit; /*8bit,1stop bit,parity none,tx enable, rx enable,rxie enable*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x40; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); return 0; } /*************************************************************************/ /* SCI一文字送信 */ /*************************************************************************/ int SCI_Putc( int ch, char c ) { SCI_REG *sci = Select_SCI( ch ); if( sci == (SCI_REG *)0 ) return (-1); while( !(sci->sr & TXE_Bit) ) ; sci->dr = c; return 0; } /*************************************************************************/ /* SCI文字列送信 */ /*************************************************************************/ int SCI_Puts( int ch, char *str ) { #if 1 char *ptr; unsigned short next; int count; SCI_BUFFER *snd; SCI_REG *sci; if( ch != SCI_1 && ch != SCI_2 && ch != SCI_3 && ch != SCI_4 && ch != SCI_5 ) return (-1); /**/ if( SndSizeOfBuf( ch ) == 0 ) return (-1); /*書き込む余裕が無かった場合*/ sci = Select_SCI( ch ); snd = sci_snd[ ch ]; /*バッファの選択*/ count = 0; ptr = (char *)snd->buf; while( *str ) { next = snd->wptr + 1; /*ポインタを進めてみる*/ if( next >= snd->size ) next = 0; /*書き込みポインタの丸め*/ if( next == snd->rptr ) break; /*代入出来ない時*/ ptr[ snd->wptr ] = *str++; /*バッファに代入*/ sci->cr1 |= TXEIE_Bit; /*送信割込み許可*/ count++; /*書き込んだカウント値を更新*/ snd->wptr = next; /*書き込みポインタを進める*/ } return count; #else while( *str ) (void)SCI_Putc( ch, *str++ ); return 0; #endif } /*************************************************************************/ /* SCI受信バッファの受信サイズ */ /*************************************************************************/ unsigned short RcvSizeOfBuf( int ch ) { SCI_BUFFER *rcv; unsigned short w,r; rcv = sci_rcv[ ch ]; /*バッファの選択*/ w = rcv->wptr; r = rcv->rptr; if( w == r ) return 0; else if( w < r ) return w + rcv->size - r; else return w - r; } /*************************************************************************/ /* SCI送信バッファの空きサイズ */ /*************************************************************************/ unsigned short SndSizeOfBuf( int ch ) { SCI_BUFFER *snd; unsigned short w,r; snd = sci_snd[ ch ]; /*バッファの選択*/ w = snd->wptr; r = snd->rptr; if( w == r ) return snd->size - 1; else if( r < w ) return r + snd->size - w - 1; else return r - w - 1; } /*************************************************************************/ /* SCI受信バッファから1文字取得 */ /*************************************************************************/ int SCI_Getc( int ch ) { int c; char *buf; SCI_BUFFER *rcv; rcv = sci_rcv[ ch ]; /*バッファの選択*/ if( RcvSizeOfBuf( ch ) == 0 ) return (-1); buf = (char *)rcv->buf; c = buf[ rcv->rptr ]; if( ++rcv->rptr >= rcv->size ) rcv->rptr = 0; return c & 0x00ff; } /*************************************************************************/ /* SCIステータスの読み出し */ /*************************************************************************/ unsigned long SCI_Status( int ch ) { SCI_REG *sci = Select_SCI( ch ); return sci->sr; } /*************************************************************************/ /* SCIステータスの読み出し */ /*************************************************************************/ char SCI_DirectRead( int ch ) { SCI_REG *sci = Select_SCI( ch ); return sci->dr; } /*************************************************************************/ /* SCI色々割り込み */ /* どうも要因別の割り込みは無いみたいだな */ /*************************************************************************/ void SCI_ISR( int ch ) { unsigned short next; volatile unsigned long status; char data,*ptr; SCI_REG *sci = Select_SCI( ch ); SCI_BUFFER *rcv; SCI_BUFFER *snd; status = sci->sr; /*各種エラーのチェック*/ if( status & (FE_Bit | PE_Bit | NE_Bit | ORE_Bit) ) { data = sci->dr; /*エラーステータスを解除する為にはデータレジスタの読み込みが必要*/ return; } /*受信割り込みの判定*/ if( status & RXNE_Bit ) { data = sci->dr; /**/ rcv = sci_rcv[ ch ]; /*バッファの選択*/ ptr = (char *)rcv->buf; next = rcv->wptr + 1; if( next >= rcv->size ) next = 0; if( next == rcv->rptr ) return; /*上書きは禁止されるので、入らない分は破棄*/ *(ptr + rcv->wptr) = data; rcv->wptr = next; } /*送信割り込みの判定*/ if( status & TXE_Bit ) { snd = sci_snd[ ch ]; /*バッファの選択*/ if( snd->rptr == snd->wptr ) /*送信すべきデータが無い時*/ { sci->cr1 &= ~TXEIE_Bit; /*送信割込み禁止*/ return; } ptr = (char *)snd->buf; sci->dr = *(ptr + snd->rptr); if( ++snd->rptr >= snd->size ) snd->rptr = 0; } } /*************************************************************************/ /* end of file */ /* designed by hamayan since 2008/11/06 */ /*************************************************************************/
stm32f10x_it.cの割込み処理のところ
/******************************************************************************* * Function Name : USART1_IRQHandler * Description : This function handles USART1 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void USART1_IRQHandler(void) { SCI_ISR( SCI_1 ); }
ARM Cortex‐M3システム開発ガイド―最新アーキテクチャの理解からソフトウェア開発までを詳解 (Design Wave Advance)
- 作者: Joseph Yiu
- 出版社/メーカー: CQ出版
- 発売日: 2009/05
- メディア: 単行本
ARM組み込みソフトウェア入門―記述例で学ぶ組み込み機器設計のためのシステム開発 (Design Wave Advanceシリーズ)
- 作者: Andrew N. Sloss
- 出版社/メーカー: CQ出版
- 発売日: 2007/08
- メディア: 単行本
2009-10-03 02:26
nice!(0)
コメント(1)
トラックバック(0)
遅レスですが、、
ちょうどSTM32 Primer2でUSARTを割り込みベースで動かそうと思っていましたので参考にさせていただきます。送受信バッファ制御のコードはそのまま拝借するかもです。
Primer2では割り込みベクターがCircleOS管理になっているため(RAMにテーブルを移動しています)、一部CircleOS依存の独自コードになってしまいます。ただ、色々便利な機能(FAT FSやLCD表示など)提供してくれるためついつい堕落して一から作るのをさぼってしまいます。
by todotani (2009-10-08 21:00)