2015年1月2日金曜日

STM32F4 でシリアル通信(割込みなし)

STM32F4 discoveryのUART2を使って、パソコンにメッセージを表示させてみた。

途中、sprintf()を使ったところで、_sbrkがないよというリンカエラーが発生した。
google先生に聞いたところ、通常はsyscalls.cで定義されている関数らしい。
syscalls.cはねむいさんのサンプルプロジェクトに同梱されていたので、使わせてもらう。
そのまま使うと、putch()とgetch()がないよと言われる。取り合えず今のところは標準入出力をそのま使わないので、syscalls.cの上のほうで中身のない、空の関数宣言してエラーを回避する。

UARTのような、特定機能(alternate function)を使う場合の手順は以下のようにする。

  1. 特定機能が割り当てられているGPIOのクロックを有効化する
  2. 特定機能のクロックを有効化する
  3. GPIOの設定をする(特定機能モードにする)
  4. 特定機能の設定をする
  5. デバイスの端子を特定機能に割り当てる

※ところで、今回alternate functionを特定機能と呼んだけれど、分かりやすい和訳は何だろう?直訳すると代替機能、ニュアンス的には周辺機能。プルチプレクサと同じことなんだろうけれど。



取り合えず動いたプロジェクトをこちら(stm32f4_uart01.zip)に保管します。

ソースコードは以下。





#include "stm32f4xx.h"
#include "uart.h"

void uart2_init(int baudrate){
  /* structure to initialize GPIO */
  GPIO_InitTypeDef GPIO_InitStructure;

  // --------------------------------------------------
  // Port A 設定(UART2 入出力) ここから
  //GPIOAとUSART2にクロック供給
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  //GPIOAのPIN2を出力に設定
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2 ;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 //GPIOAのPIN2をオルタネィテブファンクションのUSART2に割り当て
  GPIO_PinAFConfig(GPIOA , GPIO_PinSource2 , GPIO_AF_USART2);

  //USART初期化用構造体を作る
  USART_InitTypeDef USART_InitStructure;

  //USART2を9600bps,8bit,ストップビット1,パリティなし,フロー制御なし,送受信有効に設定
  USART_InitStructure.USART_BaudRate   = baudrate;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits   = USART_StopBits_1;
  USART_InitStructure.USART_Parity     = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode       = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART2, &USART_InitStructure);

  //USART2を有効化
  USART_Cmd(USART2, ENABLE);

  // Port A 設定(UART2 入出力) ここまで
  // --------------------------------------------------
}

void USART_putc(USART_TypeDef* USARTx,char c){
 while(!(USARTx->SR & 0x00000040)); //前回の送信が終わるまで待機
 USART_SendData(USARTx,c);
}
 
void USART_puts(USART_TypeDef* USARTx,const char *s){
 int i;
 for(i=0;s[i]!=0;i++) USART_putc(USARTx,s[i]);
}
 
#include 
#include 
#include 
void uart2_printf(const char *format, ...) {
 va_list list;
 va_start(list, format);
 int len = vsnprintf(0, 0, format, list);
 char *s;
 s = (char *)malloc(len + 1);
 vsprintf(s, format, list);
 USART_puts(USART2,s);
 free(s);
 va_end(list);
 return;
}


0 件のコメント:

コメントを投稿