STM32およびFreeRTOS。 5.私たちは善と善をもたらします!

念のため、それ以外の場合は制裁が適用されます(メール)。 説明されているケースは現実とは関係なく、完全に著者の発明です。



以前は、 スレッドセマフォキュー 、およびHALに関するものでした



一度、彼らは私に非常に高価なデバイスを見るように頼んだ。 1つの問題がありました:このデバイスを使用している人の中には、その価格の99.99%がこのデバイスの製造業者がその分野の独占者であり、このデバイスのユーザーが行く場所がないという事実から強い信念がありました。







オシロスコープで武装して、私は中に登った。



しばらくして、検索により、デバイスのユニットを接続するバンドル内にある2本のワイヤが見つかりました。 波形は、配線がほぼ通常のUSARTであることを示しました。 ほとんど-データが9600の速度で実行され、115200に戻ったためです。



彼は2つのusb-usartアダプターを取り出し、それらの入力をRX / TXにフックし、プロトコルの分析を開始しました。 タスクは、異なる速度、非同期、およびバイナリプロトコルによって複雑になりました。 一般的に、しばらくして、端末で何が起こっているのか、何に応答しているかを追跡しようとして、目が広くなっていることに気付きました。



同様の状況で視力と理由を保存するために、usartハードウェアスニファーを作成しましょう。 さらに、転送の速度と順序が彼にとって重要ではないようにします。 さて、usartを理解した後、脚の分析とあらゆる種類のSPIを同時に追加できます。



スニファーの作業は簡単です。STM32には、多数の組み込みUSARTがあります。 2人にRXレッグを聞かせてから、USB経由で送信します。 そして、これらの脚を調査中のデバイスのRX / TXに取り付けます。



開始するには、すでに(できれば)使い慣れたSTM32F3DISCOVERYボードを使用し、STM32Cubeを使用してブランクを作成します。 この空白には次のものが必要です



5スレッド。



defaultTask-「デバイスは機能し、ハングしません」LEDが点滅します

Usart1Rx-最初のポートでデータを受信します

Usart2Rx-2mで同じこと

UsbSend-ここでデータが処理されて送信されます

Usart3Tx-これは有名なロボットから引用を送信するテストストリームになります。 「入力への」最初の2つのポートの操作性をチェックするために使用します。 まあ、または甘やかすため。



そして1ターン-データの「受信者」からのパッケージが追加されます。 気にしないために、私はそのような構造を作りました



typedef struct { uint8_t usart; uint8_t byte; } myMes;
      
      







まず、最も重要な関数-テストデータの送信-を作成します。



 for(;;) { // Wall-e: Eeeee... va? uint8_t walle[]="Eeeee... va?\r\n"; // Short Circuit: Johny Five is Alive! uint8_t johny[]="Johny Five is Alive! \r\n"; // StarWars uint8_t c3po[]="Sir, the possibility of successfully navigating an asteroid field is approximately 3,720 to 1 \r\n"; HAL_UART_Transmit(&huart3,(uint8_t *)&walle,15,16); //PB10 HAL_UART_Transmit(&huart2,(uint8_t *)&johny,23,100); //PA2 HAL_UART_Transmit(&huart1,(uint8_t *)&c3po,97,100); //PC4 osDelay(1000); HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_15); }
      
      







そして、適切な脚用の外部usart-usbアダプターで簡単に確認して確認します。 これにより、ボード上でRX-TXレッグを直接接続するだけで、少なくとも「受信」で何が期待できるかを理解できます。







それでは、受け取ったものを受け入れて形式化する関数に移りましょう。



 xQueueReceive( RecQHandle, &w, portMAX_DELAY ); if(oldusart!=w.usart || char_count>16) { oldusart=w.usart; newline=1; char_count=0; } buf[char_count++]=w.byte;
      
      





前の記事とC言語の知識から、次の「前提」を待っているだけで、条件に応じてフラグを設定することが明らかになりました。



それでは、USBインターフェイスの準備が整い、ラインが形成される(それがより正確になる可能性がある)のを待って、ユーザーに表示します。 ここではペイントしませんでした。最適化せずに、「額に」バッファーとラインを使用するからです。



次に、データの受信元を記述する必要があります。



 void Usart1Rx(void const * argument) { /* USER CODE BEGIN Usart1Rx */ /* Infinite loop */ for(;;) { if(HAL_UART_Receive_IT(&huart1, &b1,1)==HAL_OK) { HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_9); } osDelay(1); } /* USER CODE END Usart1Rx */ }
      
      





Usart2Rxはまったく同じです。 どちらかといえば、実際のコードで私は好奇心users盛なユーザーのためにコメントを残しました。



最後に、USART割り込みハンドラー



 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) { myMes m; HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14); switch((uint32_t)UartHandle->Instance) { case (uint32_t)USART1: HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_10); m.usart=1; m.byte=b1; xQueueSend( RecQHandle, &m, portMAX_DELAY ); // Do this need? //HAL_UART_Receive_IT(&huart1, &b1,1); break; case (uint32_t)USART2: HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_12); m.usart=2; m.byte=b2; xQueueSend( RecQHandle, &m, portMAX_DELAY ); HAL_UART_Receive_IT(&huart2, &b2,1); break; } }
      
      







中央のコメントと、2番目のポートでコメントアウトされない理由に注意してください



気配りのある読者の一人のリクエストで: また、割り込みハンドラーでxQueueSendFromISRの代わりにxQueueSendを使用したことに注意してください これは意図的に行われるため、テストプロセス中にコントローラーが "できるように"(または、簡単に言えば、シリアルポートの速度を57600-115200に上げると)定期的にハングし始めます。 デバッガをオンにするだけで、混雑したキューに書き込もうとしているときに待機していることがわかります。 実際のコード内には、これらの「トラップ」がさらにいくつかあります。



コンパイル、アセンブル、ターミナルを見る







必要なようです。 別の「データソース」を1番目のポートにフックし、単純に文字列をそのポートにコピーします。







ところで、「どのように割り込みが機能するか」試用のための非常に良い質問は-なぜ両方のポートからのラインが互いに割り込まないのですか?



しかし、すべてがそれほど悪いわけではないことを確認するために、キーボードをノックした場所に別のスクリーンショットを用意します







ご覧のとおり、「sho」がある場合、1つのポートが他のポートを「kill」できます。



そして最後に、結果のアナライザーの最も興味深い機能。 物理USARTポートの初期化コードに次の行を追加する場合



 huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED ; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_AUTOBAUDRATE_INIT; huart1.AdvancedInit.AutoBaudRateEnable = UART_ADVFEATURE_AUTOBAUDRATE_ENABLE; huart1.AdvancedInit.AutoBaudRateMode = UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;
      
      







そのマイクロコントローラ自体が、オンザフライで、スタートビットの速度に調整します。 最初に低速で識別のためにデバイスが「スニッフィング」され、その後高速に切り替わる場合に非常に便利です。



それだけです。 シードに戻る:モジュール間の交換ダンプは完全に類似した方法で取得されました。かなり迅速に「突く」ことは部品に分解され、しばらくすると高価なデバイスがキー(顧客用)パラメーターでそれを超えるstobaxボックスに置き換えられました。 確かに、プロデューサーはまだお金を払うのを止めていませんでした(他にも多くの理由がありました)が、「故障してプロセスを制御する必要がある」という恐怖を取り除きました。



いつものように、ソースの完全なセットはここで取得できます



PSヘッダーの写真は、studiovsemoe.comでファームウェアを作成したレーザー手術装置のモデルです。 デバイス自体とは関係ありません。 ちょうど美しい写真が判明しました。



All Articles