投稿

ラベル(Blue Pill)が付いた投稿を表示しています

STM32 Timer

イメージ
 STM32 Timerのタイマー タイマーの設定 実は、下に書いてあるように設定して、動かしていると思っていたのにLEDがついたらつきっぱなしで思った通りの動きをしなかった・・・・かと言って何かしましたか?というと一晩寝かせて朝やったら動いた・・・(やった事は、桁で数字をかえる、分周率を7200、36000といった具合に・・それで元の数字に戻ったころにちゃんと動いた・・・謎) 先に時間を操作するので、基準になるクロックの設定をする。 RCCからHSEにCrystal/Ceramic Resonator クロックの画面で各クロックを設定 ここではTimer4を使ってみた。 Internal clockにチェックを入れると下の設定画面が出てくる。 Prescalerを設定 後で設定するクロック(ここでは72MHz)の分周率。7200(1はゼロから始まるから) 72MHz=72000kHzなので7200で割ると10kHz。 1秒のタイマーにするには、10000カウントという事になる タイマーだけ設定しても何も起こらないのでオンボードのPC13をOutputに設定して、LEDを点灯させると static void MX_TIM4_Init(void) { 中略・・・   /* USER CODE BEGIN TIM4_Init 2 */   HAL_TIM_Base_Start_IT(&htim4);   /* USER CODE END TIM4_Init 2 */ }   HAL_TIM_Base_Start_IT(&htim4);でタイマーをスタートさせる命令。 コールバックされたら、ピンをトグルするように記載して点滅間隔でタイマー割り込みを確認する。 /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){     static short Led = 1;     if (htim == ...

ADS1115 STM32 HAL

イメージ
STM32F103(blue pill):12ビットのADC搭載 読み取り精度が必要な時に16ビットなどが欲しい。1chならMCP3425が有名で秋月で簡単に購入できる。一方いくつもとなるとMultiplexerが搭載されているマルチチャンネルが読めるものが必要 入手性から ADS1115 を購入してみた。アマゾンでADCを調達しようとするとこれが出てくる。MCP3425から比べると大きい(4ADC分あるからといえば)。 また16ビットとなっているが、フルスケールがプラスマイナスなので実際は正側だけ使う場合は、15ビットの分解能になるとはいえ、フルスケールも選択できるので分解能はFSが狭ければ稼ぐ事もできる。 使い方のメモ。 【動作】 動作させる主な手順 1.レジスタとしてAddress Pointer registerに書き込みConfig Registerを指定する。 2.Config Registerに設定を書き込む 3.レジスタとしてAddress Pointer registerに書き込みConversion  Registerを指定する。 (Conversion  Register:16ビットのAD変換の結果が格納されるレジスタ) 4. Conversion  Registerの内容を読み込む 上記で書き込み時には、 R/Wビットはゼロ(LOW)で、読み込む時は、1(HIGH)にする。 【アドレス】I2Cのアドレスは4種類から選べ、メカで(ハードの時点で)ADDR Pinをどこに接続するかで決められる。1つの4ch分を使うのであれば、GNDにでも繋いでおく。 【手順1】Config Registerを指定する。 レジスタとして、 Conversion  Register:16ビットのAD変換の結果が格納されるレジスタ Config Register:各種の設定をするレジスタ Lo thresh Register/ Hi  thresh Register:コンパレーターの機能をもっていて閾値を設定できる(ここで指定した値に入るとALERT/RDYのピンの出力を変動させる事ができる。モードが通常とコンパレーターとWindowモードがあり、出力を制御できる。このあたりはデータシートを参照。) ...

STM32 Blue Pill(STM32F103C8T6)の容量

イメージ
Blue Pill(STM32F103C8T6)の容量が64kと公称されているが、実際は128kの容量を持っていると多くのブログなどで記載があった。 本当に?→ どうも64kを超えてもちゃんと動くようです。  STM32F103C8TX_FLASH.ldのファイル内に、 * Memories definition */ MEMORY {   RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K   FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH =128K } 128Kに書き換えるだけ・・・ 表示が128kになるだけではなくて、128Kの50%を超えてちゃんと書き込みできているようです。ダンプしてまでは確認してないが、動いているので問題はないようです。 https://drive.google.com/file/d/18emCZnAIXVuJ4SWqdAxn36qhAmPHlWW6/view?usp=sharing

STM32 MCP3425 via I2C

イメージ
 SPIからOLEDに文字を出す際は、先人が作ってくださっている関数をダウンロードしてきて使っていた。世界で有名どころならそれでよいが、つかうICのデータシートを紐解いてI2Cで設定する。 対象:MCP3425。Arduinoから超有名なADCで大量に情報は得られる。 まず、上の方で、 /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ #define MCP3425_address  (0x68 << 1) 次に /* USER CODE END PTD */   /* USER CODE BEGIN 2 */   uint8_t MCP3425_ConfREG=0b10011000; //16bit 15sps PGA x1   uint16_t adcdata;   float Vref_cp3425=2.048;   float Vmcp3425=0;   HAL_I2C_Master_Transmit(&hi2c1,(uint16_t) MCP3425_address, &MCP3425_ConfREG, 1, 100);  /* USER CODE END 2 */ とmainの前で、設定をし ADCの値を取得したところで HAL_I2C_Master_Receive(&hi2c1, (uint16_t)MCP3425_address, &MCP3425_buffer, 2, 100); adcdata=(MCP3425_buffer[0]) <<8 | MCP3425_buffer[1]; Vmcp3425=adcdata*Vref_cp3425/32767.0; で取り出せる。 【解説】 Address byte MCP3425のアドレスは、秋月から購入すると、0x68。 2進数で01101000。アドレスバイトは、最後がR/W(ICから見て受信か送信か)を選択するビットが入って1バイト。Arduinoとかこの点、ユーザが知らなく...

STM32 ADCのノイズ

イメージ
STM32F10XなどのADMは12bitなので4096階調、3v3 /4096=0.0008V/setp 0.8mV程度はADCの変換の結果が揺れてもよいが、実際はその10mVの桁で下手するとゆれる。要因の切り分けと対策。オシロがないので、データを連続的に取り込んでの比較。 このテストには安定化1.50Vの電源を使っている。ただし、STM32への電源はPCバスを使っている(データ取り込みのためUSBに接続せざえる得ない) 【無対策:この上の青色】250点の標準偏差の平方根: 0.02058392952 青が何も対策しない場合・・・ひどい。定常的に10mVぐらいは揺れているし、時折ピークが見える。なんかのクローストークなんでしょうね。 【対策:パスコン104挿入。この上の赤色】250点の標準偏差の平方根: 0.002067946739 センサー側からのノイズをひらってしまって揺れているのを幾分かカット、効果はあり標準偏差(平方根)は一桁下がった。 【対策:プルアップ外部化。この下の黄色】250点の標準偏差の平方根: 0.001570396705 パスコンを入れた状態で、同じ回路内に、スイッチの検出のために内部でプルアップしていると、そこからのリークにより増える説。グラフ上はほぼ同じだが、標準偏差を見ていると確かに若干の効果はあり。 【対策:デジタルフィルタ】 ADCを連続的に行って平均をとるとか、移動平均をとるとか統計処理をするのが考えられるんですが、最後はデジタルフィルタ。 ADC_array[1]=ADC_array[0] *0.8+0.2*ADC_buff[0]; ADC_array[0]=ADC_array[1]; V1[0]=ADC_array[0]/4095.0*3.3; 一つ前の値に、新しい値を2割だけ入れる。この割合でフィルター度合がきまるし、応答時間も決まる。パスコンを入れた状態で計測したのが↑の赤線。MUPを使う場合、メモリの制約などもあるため、簡単にというと一つの手法としては有効。(RCフィルタと同じなので振幅が大きいものを測定しようとすると注意が必要。) 【まとめ】250点の標準偏差の平方根を比べた結果 STD Non 0.02058392952 0.1uF 0.00206794673 non Pull up 0.00157039670 Di...

STM32 RS-232C via USART

イメージ
ArduinoでのRS-232C制御は以前に行った。STM32からAMD3202を介してのRS232-C. 1.ピン配置  ConnectivityでUSARTを選択(この場合は、干渉のないUSART3を選択)。modeとしてAsynchonousを選択。他はデフォルトでOK。 2・コーディング   uint8_t Knum=0;   /* USER CODE END 2 */   /* Infinite loop */   /* USER CODE BEGIN WHILE */   while (1)   {   /*RS-232C via USART*/   if (Knum==0){   char RS232msg[] ="K1\n";   HAL_UART_Transmit(&huart3,(uint8_t *)RS232msg,strlen(RS232msg),500);   Knum=1;   }   else{   char RS232msg[] ="K0\n";   HAL_UART_Transmit(&huart3,(uint8_t *)RS232msg,strlen(RS232msg),500);   Knum=0;   }   char RS232msg2[] ="K?\n";   HAL_UART_Transmit(&huart3,(uint8_t *)RS232msg2,strlen(RS232msg2),500);   HAL_Delay(1000);   char USART_buff[128];   memset(USART_buff, 0, 128);   HAL_UART_Receive(&huart3, (uint8_t *)USART_buff,sizeof(USART_buff), 500);   HAL_Delay(1000);   ssd1306...

STM32  ArduinoでいうところのINPUT_PULLUP

イメージ
 ArduinoでいうところのINPUT_PULLUP GPIOから、GPIO_InPutモードを選択して、それぞれの端子でGPIO Pull-up/Pull-downの項目でPull-upを選択決定する。あとは、結線上は、同じでGNDに落ちたら検出をする。 /*changing of set value by switch */   while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){        if ((Vset >= 0) && (Vset <= 1.499)) {        Vset=Vset+0.001;       sprintf(cdcBuffer, "Vset=%4f\n\r",Vset);       ssd1306_SetCursor(0, 8*3);       ssd1306_WriteString(cdcBuffer, Font_6x8, White);       HAL_Delay(1);       ssd1306_UpdateScreen();         } 上は、押している間、Vsetの値が0.001増え(長押し可能)、この例の場合はOLEDでもその増えていく様子がわかるってもの。

STM32 ADC DMA

イメージ
 STM32 ADC DMA 割り込みで読むという方法などがあるが、連続的に読むやり方。 1.ピン配置 AnalogからADC1を選択(別にADC2でもよい、上の例では4チャンネル分を指定。すでにSPIと競合しているピンが赤くなっている) 下のタブをDMA Settingにきりかえ、Addを押す。 ModeをCircularをしていして、Memoryの方にIncrementのチェックが入っているか確認する。 Parameter Settingのタブ Continuous Conversion Mode Enable Number of Conversion を読み取る端子の数、ここでは4 それぞれRank違いで、Sampling Timeを設定し、Channel0から1、2と使うチャンネル分増やす。Sampling Timeここは長くっとっておいて様子を見て早くする(計算すればよいんだろうけど・・・) ADCについての詳しい解説: STM32 ADC Tutorial - Complete Guide With Examples - DMA / Interrupt (deepbluembedded.com) Clockの方も必要に応じて編集する。 ADC prescalerを/6を選択して12MHzに設定した。 ここまでできたら保存してコードを吐き出す。 2.コーディング   /* USER CODE BEGIN 2 */ //ADC setting uint16_t ADC_buff[4];   while(HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK);           // calibrate AD convertor   if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_buff, 4) != HAL_OK)   {   Error_Handler();   }   /* USER CODE END 2 */ メイン部分は  /* Infinite loop */  ...

STM32 SPIによるMAX5144

イメージ
 STM32 SPIによるMAX5144 1・ピン配置 ConnectivityのSPI1を選択、SSピン(素子選択)用に隣のピン(PA4)をGPIOのOUTに指定する。通信速度があり、Prescalerのところで倍率を設定することができる。18Mとかが設定可能。ただ配線などに気を配らないとあまり早いと送り込む命令が0xFFFF→0x0000とかで急激に変化するところでエラーを起こしていた事があり、そこそこに設定している。 結構、はまるで最初はゆっくり目からスタートして動く事を確認してからはやくするなどがおすすめ。 POLARITYは、素子選択がLOWで検出(選択されれない時HIGH)なのか、またその逆か?1EDGEは、立ち上がりを検出2EDGEは立下り検出など。モードが全部で4種類ある事になる。ここいらは使うSPIの素子のデータシートを見て設定する。MAX5144はモードゼロ。 2,コーディング  /* USER CODE BEGIN 2 */     //DAC variables     float Vset=0.740;     float Vdacref=1.500;//5144のREFに入力している電圧。ここでは1.5V。     uint16_t DataInt;     uint8_t Datatemp1;     uint8_t Datatemp2;     uint8_t temp[2]; DataInt=Vset/Vdacref*16384;//5144は14bitのDAC。 DataInt=DataInt <<2;//0010 0000 1010 0101→1000 0010 1001 0100 Datatemp1=DataInt >> 8; //0000 0000 1000 0000 Datatemp2=DataInt & 0xFF; //0000 0000 1001 0100 temp[0]=Datatemp1;// temp[1]=Datatemp2; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4...

STM32 USB経由によるシリアルの送受

イメージ
 BluePillを計測器として利用することを想定するとPCからのコマンドを受け付けた時に、機器の状態をPCに返すというような使い方を想定 USBポートを介してのシリアルのやりとり。中華ST-LINK利用時デバッグできない問題を回避するために使うというようなページは多数あるので参考に。 1.ピン設定 Connectivityの下のUSBを選択。窓の上のDvice(FS)にチェックをいれる。その他はデフォルトでOK。 次に、MiddlewareのUSB_DEVICEを選択して Class for FSIPをCommunication Device Class(Virtual Port Com)に変更 2.Clockの設定 System Coreの下にあるRCCを選択。High Speed Clock (HSC)をCrystal/Ceramic Resonatorを選択。 その後、上のタブでClock Configrationを選択して、クロックを設定(一例は以下) USBのクロックが48MHzになるように調整し、APB1のクロックが36MHzになるように設定をする。 ここまでできたらセーブして、コードを生成させる。 3.コーディング 書き込み(マイコン→PC)は簡単なので詳細は割愛 /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ char cdcBuffer[40]; /* USER CODE END PD */ cdcBufferとか適当に宣言しておいて、 sprintf(cdcBuffer, "ch%d=%4f\n\r",1,Vtemp); while(CDC_Transmit_FS((uint8_t*)cdcBuffer, strlen(cdcBuffer)) == USBD_OK) {} とすればOk。(ここではVtempはfloatの変数を想定) PCから文字列を受け取る方がちょっと複雑 main.c内にUSBからのやり取りのためのバッファーを定義 /* Private user code --------------------------------------------...

STM32でSSD1306 OLED 128x

イメージ
 STM32でSSD1306 OLED Oliverさんという方が作られたライブラリーとそれを改変してSPIにも対応した Aleksander さんという方が作られたライブラリー。前者は128x32への対応をすると上手くできず、後者を利用。I2Cでの通信(ライブラリーを利用)。 1.ピンの割り当て Connectivityの下のI2C1(または2)を選択して、上側の窓のI2Cの欄から、I2Cを選択 その他は、特段デフォルトでOK。(あえて言うならClockSpeed = 100000のところを好みで)保存して、コードを吐き出す。 2、ライブラリーのダウンロードと取り込み https://github.com/afiskon/stm32-ssd1306 からZIPで一式ダウンロードする。DLしたファイルから必要なのは ssd1306_fonts.h ssd1306_conf.h (←ssd1306_conf_template.hが入っているが名前から_templateを削除) ssd1306.h ssd1306.c ssd1306_fonts.c hファイルとcファイルそれぞれIncとSrcにCureIDEのProject Explorerにドラッグ。 3,設定 ssd1306_conf.hを開いて、使うMPUにあわせて、コメントアウトを調整。また下の方に、サイズがあるので、使うサイズにあわせて変更する。 3,コード 2つのヘッダーファイルをincludeする /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "ssd1306.h" #include "ssd1306_fonts.h" /* USER CODE END Includes */ 基本的な使い方は、以下。 ssd1306_Init();で初期化 ssd1306_Fill(Black);で一度画面を消す。 ssd1306_SetCursor(0, 0);はカーソルの位置を指定。 ssd1306_WriteString(str_temp, Font_6x8, White);で書き込...

RS-232Cを理解する

イメージ
もはや骨董品になりつつあるRS-232C。ここの目的は、マイコンのTX,RXからテキストのコマンドを送りつけて、機器とRS-232Cと通信することをめざす。テストとして、 NEW portの光パワーメーターのRS-232Cで制御する。 https://www.equipland.com/objects/catalog/product/extras/1030_1830-c.pdf その前に、RS-232Cのピンについてのお勉強。装置のマニュアルに掲載されているピン配置 装置側 PC側 各ピンの役割 DTE DCE 1 DCD Data Carrier Detect モデムでデータ通信する時。1にしておく 1 CD Carrier Detect (キャリア検出) 2 RxD Recieve Data 受信データライン 2 SD Send Data (送信データ) 3 TxD Transmit Data 送信データライン 3 RD Recieve Data (受信データ) 4 DTR Data Terminal Ready こちらの電源が入っている事を相手に教えてあげる。1の時電源ON 4 DR Data Set Ready (データセットレディ) 5 GND Ground GND。信号のグランド 5 SG Signal Ground (シグナルグランド) 6 DSR Data Set Ready 相手側の電源が入っているか確認。1の時電源ON。 6 ER Equipment Ready (データ端末レディ) 7 RTS Request to Send 送信要求、ゼロの時相手は送信を止める 7 CS Clear to Send (送信可) 8 CTS Clear to Send 7RTSの逆。1との時こちら側からデータを出力する 8 RS Request to Send (送信要求) 9 RI Ring Indicator モデムからの受信している間1になる オープン 9   ↑から自作で回路を作製する際、7&8番ピンの直結しておき、 マイコンからの送信要求(7番ピン)に対し、無条件に送信可(8番ピン)を返すようしておけばとりあえずはよさげ。 他に必要なのは、5番ピンはグランドと、2番ピンと3番ピンがマイコンからの制御信号のやり取りに使う。 一通り理解が進...

ブルーピル事はじめ

イメージ
STM32 STM32F103C8T6 ブルーピル 概念の理解:Arduinoとの比較(個人的な解釈) 【IDE環境】 Arduinoの場合→Arduino IDE STM32の場合→ STM32CubeMX 、 STM32CubeIDE いろいろあるがST社のもの。情報量も多い。 【インストールではまった!】 STM32CubeIDE を使うことを前提に、IDEだけをインストールすると、パッケージをダウンロードする際に、”Error downloading the following files."とメッセ―じが出ててしまう。STM32F103のパッケージをDLするも止まる。手動でインストールするものの、うまくビルトできない事態に・・・ Error downloading the following files (st.com) ↑ ここに記載されている症状が出る。ここでも問題は解けていない。 で、家でインストールしたときはできて、職場でできなかった事から何が違うか? 解決方法 MXを先にインストールする。MXの状態ではすんなりSTM32F103などのPKGが自動でダウンロードされる。その状態を確認してから、IDEをインストールする。 するとサクッと問題が解決された。同じ症状で困っている場合は、お試しを。 【ピンアサイン】 Arduino→そもそもピンはアナログとデジタルで固定で、INPUT、OUTPUTを指定 例:void setup() {   pinMode(PIN_LED0, OUTPUT);   pinMode(PIN_SW,   INPUT); } void loop() {   digitalWrite(PIN_LED0, 1);   digitalRead(PIN_SW)); } STM32 STM32CubeMXのソフトから指定する。GPIOなので、それぞれのピンの役割を個別に指定できる。Loopに相当する while (1)の箇所にコードを記載していく点は同じ  while (1)   {     /* USER CODE END WHILE */     /* USER CODE BEGIN 3 */   } 【...