スキップしてメイン コンテンツに移動

BluePill stm32f103c8t6でシリアル出力の簡易時計

表題の通りなんですが、サンプルがないかと調べたところ意外と他には見つからなかったのですが、簡易的にですが動作するところまで来たので、忘備録として挙げてみることにしました。
プログラム環境はCubeIDE、デバッガはSTLINK V3 MINIEを使いました。
まずプロジェクトを新規作成します。File -> New で STM32 Projectをクリックします。次に使用するMCUを選びます。今回はSeries STM32F1を選択してから、f103c8t6をさらに選択して"Next"をクリックします。今度はProject Nameを聞いてくるので、今回はBluePill_stm32f103c8t6_serial_clock01としました。プロジェクト名を入力したら、"Finish"をクリックします。これで新規プロジェクトは作成されたので、続いてCubeMXをつかってコンフィグを行います。
まず、"Pinout & Configuration"で、System Core -> RCCを選択し以下のようHSEとLSEを設定します。
続いて"Pinout & Configuration"で、System Core -> SYSを選択し以下のようにSWDデバッグピンを有効にしておきます。
続いて"Pinout & Configuration"で、Timers -> RTCを選択し以下のようにクロックソースとカレンダーをアクティベイトさせておきます。
続いて"Pinout & Configuration"で、Connectivity -> USART1を選択し以下のようにしておきます。
続いて、RTC global interrupt(割り込み)を有効にするため、"Pinout & Configuration"で、System Core -> NVICを選択し以下のようにRTC global interruptをEnable/Preemption Priority 4にしておきます。
最後はClock Configurationを選択し以下のようにします。
画像では見にくいのですが、RTC Clock MuxをLSEにし、PLL Source MuxをHSEにして、PLLMulを x8 に設定します。続いてSystem Clock MuxをPLLCLKにし、最後にAPB1 Prescalerを /2にします。
ここまでくるとCubeMXの設定はできたので、CTRL+Sで保存します。するとコードを生成するかきいてくる(Do you want generate Code?)のでYesをクリックし、コードを生成させます。
つぎにコーディングを行います。今回は出力にprintf, 時刻合わせにscanfをつかいます。また、stm32f103c8t6の場合、クロックデータはbcd(binary coded decimal)なのでdec2bcdなる関数を作成しました。
以下main.cの変更箇所のみですが以下のようにします。
(前略)
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdint.h>
/* USER CODE END Includes */
(中略)
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/* USER CODE END PV */
(中略)
/* USER CODE BEGIN PFP */
int dec2bcd(int dec);
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  return ch;
}

GETCHAR_PROTOTYPE
{
  uint8_t ch = 0;
  // Clear the Overrun flag just before receiving the first character
  __HAL_UART_CLEAR_OREFLAG(&huart1);

  HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  return ch;
}
/* USER CODE END PFP */
(中略)
int main(void)
{
  /* USER CODE BEGIN 1 */
  int year, month, date, hours, minutes;
  /* USER CODE END 1 */ 
(中略)
  /* USER CODE BEGIN 2 */
  setvbuf(stdin, NULL, _IONBF, 0);

  printf("Enter Year: ");
  scanf("%d", &year);
  printf("\n\rEnter Month: ");
  scanf("%d", &month);
  printf("\n\rEnter Date: ");
  scanf("%d", &date);
  printf("\n\rEnter Hours: ");
  scanf("%d", &hours);
  printf("\n\rEnter Minutes: ");
  scanf("%d", &minutes);
  printf("\n\r");

  sTime.Hours = dec2bcd(hours);
  sTime.Minutes = dec2bcd(minutes);

  sDate.Month = dec2bcd(month);
  sDate.Year = dec2bcd(year);
  sDate.Date = dec2bcd(date);

  HAL_RTC_SetTime(&hrtc, &sTime, FORMAT_BCD);
  HAL_RTC_SetDate(&hrtc, &sDate, FORMAT_BCD);

  HAL_RTCEx_SetSecond_IT( &hrtc );
  /* USER CODE END 2 */
(中略)
/* USER CODE BEGIN 4 */
/*************************************************************************/
/* RTC interrupt call back function.                                     */
/*************************************************************************/
void HAL_RTCEx_RTCEventCallback( RTC_HandleTypeDef *hrtc )
{
	HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN);
	HAL_RTC_GetDate(hrtc, &sDate, RTC_FORMAT_BIN);
	printf("20%02d.%02d.%02d %02d:%02d:%02d\r\n", sDate.Year, sDate.Month, sDate.Date, sTime.Hours, sTime.Minutes, sTime.Seconds);
}

int dec2bcd(int dec)
{
	uint8_t a, b, c, d;
	int bcd;
	a = dec/1000;
	b = (dec%1000)/100;
	c = (dec%100)/10;
	d = (dec%10);
	bcd = a << 12 | b << 8 | c << 4 | d;
	return bcd;
}
/* USER CODE END 4 */ 
コーディングは以上ですが、RTCでの秒割込は、HAL_RTCEx_SetSecond_IT( &hrtc ) で登録し、HAL_RTCEx_RTCEventCallbackで当該割込処理を行っています。
つづいてstlinkv3minieとターゲットのBluePillを接続させます。v3minieの場合、3.3vからは電源供給されないので、BluePillをUSBに接続するなどして電源を確保しておいてください。次に、stlinkv3minieとBluePillを接続します。接続自体には特に難しいところはないのですが、1.27mmピッチを2.54mmピッチに変換するアダプターが必要です。今回はこちらのアダプタを使いましたが、TXとRXが逆に表記されているようなので、注意してください。
V3MINIアダプタ	BluePill
========================
GND		<->		GND
TX		<->		PA9(TX)
RX		<->		PA10(RX)
1		<->		3.3v
7		<->		SWDIO
9		<->		SWDCLK
コーディングと接続ができたらSTLINKをPCに接続します。次にシリアル入出力を行うため、たとえばWindowsではTeraTermなどを起動させ前述のように115200/8/none/1でシリアルを設定しておきます。
最後にデバッグボタンをクリックします。初回のみ新規でConfigが作成されますので、今回はそのままOKをクリックします。コーディング、接続がただしければ例えばTeratermでは以下のようになります。

今回は以上です。それでは。

コメント

このブログの人気の投稿

wsdd を使ってSamba サーバをネットワークに表示

Windows 10のアップデートで、セキュリティー対応のため、smbv1がデフォルトではインストールされなくなり、Samba serverがエクスプローラーのネットワークに表示されなくなってしまいました。そこで、いくつか方法を調べたのですが、linuxでwsdの実装がないか探したところ、 https://github.com/christgau/wsdd が、見つかりましたので、さっそくインストールしてみました。まだパッケージにはないようですが、インストール自身は簡単です。wsdd自体は以下のように取得し、linkを張っておきます。 cd /usr/local/bin/ sudo wget https://raw.githubusercontent.com/christgau/wsdd/master/src/wsdd.py sudo chmod 755 wsdd.py sudo ln -sf wsdd.py wsdd こちらのsambaサーバはDebianなので、/etc/systemd/system/wsdd.serviceは以下のようにしました。 [Unit] Description=Web Services Dynamic Discovery host daemon Requires=network-online.target After=network.target network-online.target multi-user.target [Service] Type=simple ExecStart=/usr/local/bin/wsdd -d MYDOMAIN [Install] WantedBy=multi-user.target wsdd -d MYDOMAINのところを、環境にあわせて書き換えてください。 次に、systemdに登録・起動テストを行います。 systemctl enable wsdd systemctl start wsdd 起動に成功すると、エクスプローラーのネットワークに表示されます。  なおこのwsddはpython3が必要です。一度試してみてください。SMBv1/CIFSを停止していても、大丈夫です。 cで書かれたほかのwsddの実装もあるようなので、いずれパッケージになるかもしれませ

Hyper-V Server2019にワークグループ環境下でWindows10(1809)から接続

Hyper-V server 2019に、ワークグループ環境にてWindows10(1809)から接続してみました。Windows10にHyper-V管理ツールがインストールされていることと、Hyper-V Serverをインストール済であることが前提です。以下、Hyper-V serverは名前がHyperVSV、アドレスは192.168.1.110としています。 まず、Hyper-V server上で、powershellを起動し、以下のコマンドを入力します。 Enable-WSManCredSSP -Role Server -Force 続いて、クライアントのWindows10のpowershell で以下のコマンドを入力します。 winrm quickconfig -Force Enable-WSManCredSSP -Role Client -DelegateComputer * -Force さらに、クライアントマシンで、gpedit(グループポリシーエディタ)を起動し、以下の要領でポリシーを設定します。 a. [コンピューターの構成]->[管理テンプレート]->[システム]->[資格情報の委任]->[NTLMのみのサーバー認証で新しい資格情報の委任を許可する] を有効にし、サーバを一覧に追加[表示...]ボタンをクリックして、「WSMAN/*」を追加 b. [コンピューターの構成]->[管理テンプレート]->[システム]->[資格情報の委任]->[NTLM のみのサーバー認証で保存された資格情報の委任を許可する] を有効にし、サーバを一覧に追加[表示...]ボタンをクリックして、「*」を追加 また、名前解決できるように、(notepadを管理者権限で実行し)C:\Windows\System32\Drivers\etc\hostsにサーバ名とIPアドレスの対を追加。 192.168.1.110 HyperVSV 最後に、Hyper-Vマネージャーを起動し、Windows10からHyper-V サーバに接続します。手順は以下の通りです。 「サーバーに接続」->コンピュータの選択->別のコンピューターに[HyperVSV]と入力し、[別のユーザーとして接続する

フレッツ光クロス:MAP-E ROUTER by Debian Box (iptables)

フレッツ光クロスがようやく開通したので、Debianにてrouterを構成し接続してみました。なお、プロバイダーを選ぶにあたっては、IPoE方式がそれぞれ異なるため検討したところ、IPoEでは、MAP-Eでもv6plusとocnバーチャルコネクトがあり、前者がポート数240なのに対し、後者は約4倍のポート数が使えるようなネットの情報をみて、OCNバーチャルコネクトを選択しました。(プロバイダーとしてはぷららです。なおDS-LiteはCE側でのNATではないので今回は見送りました。)そこで、OCN バーチャルコネクトをDebian(iptables)で実現するとどうなるかと思い、ネットの情報を頼りにしつつ、設定した次第です。 実際に試した結果、とりあえず通信できていますが、MAP-Eは本来マッピングルールをマップサーバから取得するはずなので、今回のやり方が正解とはいえませんし、仕様変更されると通信できなくなる可能性があります。あくまでも参考程度ですが、本稿をUPしてみました。 2023/03/16追記: こちら にゲームコンソールNAT越え(Nintendo Switch ナットタイプ A判定)対応版を投稿しました。 2023/03/28追記:※1の記述および3行無効化によりNAT越え(Nintendo Switch ナットタイプ B判定)できるようになりました。 構成は以下の通りです。 ルーターがDebianで回線がOCNバーチャルコネクトであること以外はなにも特別なところはない構成です。 さて、いきなり設定ですが、まず、割り当てられたプレフィックスを確認します。 確認は、 dhclient -6 -d -P enp2s0 とします。出力の中に 前略 RCV: | | X-- IAPREFIX 2400:4050:5c71:af00::/56 後略 このようにプレフィックスが表示されるので、その確認したプレフィックスを書き留めておきます。これを こちらで 入力します。すると、 CE: 2400:4050:5c71:af00:99:f171:c600:2f00 IPv4 アドレス: 153.241.113.198 ポート番号:(1776-1791 2800-2815 3824-3839) 4848-4863 5872-5887 6896-