2019年10月6日 星期日

充電一下--設定 windows 更新失敗。正在還原變更。請勿關閉您的電腦

現在幾乎家家戶戶都有電腦

而且絕大多數都是安裝微軟的 Windows 作業系統

而 Windows 有個功能叫做 Windows Update

用來檢視您的作業系統是否跟上時代的潮流

是否相容目前市面上大多數的軟硬體配備

避免您在安裝新硬體或是新程式的時候出現問題

更避免您的電腦存在被駭客攻擊的安全性漏洞

這是一個很人性化的功能

既會自動搜索需要的更新程式

又能排程在不影響電腦工作的時候進行

通常是在您電腦關機時才進行安裝

不過您遇到過 Windows 更新失敗進入無窮盡循環的情況嗎?

*****************************************************************

公司近日買了一台新電腦

因為我的電腦一天會出現好幾次藍白畫面

已經嚴重影響到工作進度

而且進行程式的編譯

常常第一次要花費十幾分鐘才能完成

這對重視效率的我來說

是完全不能接受的事

礙於公司的經費問題

直到最近才真正換了新的電腦

DELL / Windows7 / 8G DDR / SSD硬碟

開機20秒完成

關機也20秒完成

效能測試 OK

於是開始移植原先使用的工作軟體到新電腦上

剛安裝的幾個環境都挺順利的

特別是剛剛提到編譯要花十幾分鐘的程式

到了新電腦只花了不到三分鐘就完成了

初估至少快了四~五倍的時間

心想這應該可以縮短超多的工作時間了

不過就在移植了六、七個環境後

電腦開始出現要更新的訊息

而且一次就要更新137個檔案!

天阿!新電腦的作業系統是有多老舊呀!

竟然要安裝這麼多更新檔

不過身為工程師

對細節特別講究

反正新電腦的速度那麼快

就讓他安裝吧!

我還是可以繼續做其他的事

*****************************************************************

就在第一次更新關機後

電腦重新啟動

然後出現 Windows 設定中

然後.......竟然不是設定完成進入系統

而是『設定 windows 更新失敗。正在還原變更。請勿關閉您的電腦』

這是什麼情況!

而且這一還原就耗掉半個多小時

如果是原來的電腦

大概半天就不見了.......

更慘的是

還原後要關機又會再更新一次

更新完重新開機又再還原一次

就這樣經歷了三輪

還是一個半天不見了!!!

你問我為什麼讓他經歷了三輪?

因為我姓李、不信邪......XD

*****************************************************************

不過雖然經歷了三輪

並不代表我完全沒有做任何的努力

第二次重新啟動時

我就已經找了相關的解決方法

最後得到的結論是重灌就一定能解決

不然問題可能存在137個檔案的任何一個檔案裡

更可能跟這137個檔案一點關係都沒有

而是電腦本身的相容性出了問題......

身為一個嚴謹的工程師

不能忍受一台新電腦表現出外強中乾的孬樣

而身為一個浪漫的詩人

更不能忍受這種掃興耍廢的違和感

網路上一大堆的介紹都只說了:

很花時間!別鬧了!重灌比較快!

我堅持一定要找出原因......

回歸解決問題的第一步

我將大問題拆成小問題

137個檔案或許有點多

那我一次更新5~10個檔案總不會也出問題吧?

於是我進入控制台的 Windows Update 中

自己手動選擇要更新的檔案

為了驗證這個想法的方向是對的

一開始我選了檔案大小不到1MB的更新檔先安裝

一次更新10個就好

*****************************************************************

第一次更新就有一個檔案安裝失敗 (KB971033)

不過卻沒有影響開關機

也沒有進行安裝設定又還原的動作

我覺得我應該找對方向了

於是又選了10個檔案進行更新

很遺憾這次又有一個檔案更新失敗 (KB3075220)

不過也沒有影響開關機

第三次我放大膽子

一次選了15個檔案(其中包含超過1MB但不足10MB的檔案)

這一次竟然全部安裝成功!

心想問題的範圍應該縮小了

又選了17個檔案進行更新

不過這一次很神奇

安裝時的總檔案大小在一開始顯示138.6MB

可是安裝到一半忽然跳成126.9MB

安裝完成後出現一個安裝失敗(KB3019978)、一個不需要(自動消失?)

我沒記下選取的檔案

所以也沒發現是哪一個被消失了

第五次選的全部安裝成功(但有一個不需要自動消失)

第六次又出現一個安裝失敗(KB2919469)

就這樣反反覆覆重新啟動電腦十次

最後兩次安裝失敗的檔案有些是比較大型的檔案

KB4516048--306.6MB

KB4516065--288.9MB

Intel Corporation ......(balabala......)

KB4490628

就這樣把所有的更新檔又安裝了一輪

剩下四個頑強的更新檔更新失敗還不會消失

又繼續出現在更新的清單中

好吧!已經開了頭就有頭有尾吧!

接下來就是單獨安裝

KB4490628 經過兩次單獨安裝後安裝成功!

KB4516048、KB4516065 在第二次的單獨安裝也成功!

*****************************************************************

在這些檔案完成更新後

又有新的更新檔案延伸出來

這些檔案並沒有為難我

讓我很順利地完成了安裝

然而 Intel Corporation ...... 這個更新檔安裝了三次依舊沒有完成安裝

後來查了錯誤碼 80070103 所代表的意思

簡單說就是現在所使用的驅動程式比 Windows Update 所提供的還要更好

所以就別安裝了

然後電腦出現了一個很詭異的現象

就是(KB4503548 -- 適用 Windows7 x64 的 Microsoft .NET Framework 4.8 -- 35.0MB) 這個更新檔

竟然在安裝完成後,連續三次出現在更新清單中

就在我安裝完 KB4516048 及 KB4516065 之後

更有甚之

之後新出現的 KB4524157 安裝完成後

KB4503548 又陰魂不散地冒出來要更新了!!!

最後解決的方法也還是自己隱藏掉這個檔案

*****************************************************************

經由上面一連串的更新檔安裝後

我得到了一個合理的結論

Windows 的每一個更新檔有相互依存的關係

如果安裝的先後順序不對

就會發生很嚴重的更新問題

舉例來說

今天出的更新檔修正了 A 問題

兩天後又出了一個修正 A+B+C 的相容問題

如果你前面的 A 問題沒有先進行修正

某些應該存在 A+B+C 的參數可能是錯誤或不存在

此時若先安裝了後面一個更新檔

就會導致作業系統連帶將 B 與 C 兩個裝置給癱瘓了

系統判斷這樣的問題無法解決

於是自動又幫您還原回去原來沒有安裝 A 及 A+B+C 的狀態

可是為什會出現這樣的問題?

第一

你的作業系統不是每天都在準備更新的狀態

所以先下載回來的檔案往往是最近更新的檔案

因此電腦也會將先下載回來的檔案優先進行更新

導致安裝的先後順序發生問題

第二

更新檔案的大小會影響下載的穩定

檔案越大的越容易在下載過程發生錯誤

特別是網路品質不太好的地方

因此我先選用檔案較小的進行更新是有特別的用意的

如果你的更新檔是數百MB的龐然大物

遇到更新失敗時請利用網路不塞車的時間進行更新

應該可以順利更新完成

第三

當硬體驅動程式版本太久沒更新的情況下

微軟的更新檔也很可能會發生無法更新的問題

針對硬體較新版本的驅動程式所修正的更新檔

很可能造成使用硬體的不穩定

但 Windows Update 本身並沒有檢查硬體的驅動版本是否需要更新檔

就自作主張幫你的電腦更新了

這是一直無窮迴圈鬼打牆的最可能的原因之一

所以才會有錯誤碼 80070103 的存在

此時需要有智慧的您手動將這個更新檔永久隱藏

不然這個更新檔就會一直自動出現在你的更新清單中

*****************************************************************

如果下次您有遇到這樣的問題

不妨耐著性子好好地面對處理

一定可以讓你的功力一下子提升很多

不單單只是電腦

還有處理事情的思路與解決問題的手段

都會連帶一起提升唷!

KP經常引用曾國藩說的一句話:

『做大事,最重要的是耐煩。居官以耐煩為第一要義。』

在此勉勵大家,一起『耐煩』!





延伸閱讀:
後來發現KB4516048--306.6MB這一類大型檔案
可以在 Microsoft®Update Catalog 中手動下載
下載時可能會被 Chrome 視為封鎖檔案
記得在Download處按右鍵另存連結
並在下載檔案的地方選擇保留(預設是捨棄)
祝大家更新順利~~~

2019年9月27日 星期五

STM32 的 X-CUBE-MCSDK 初體驗 (使用B-G431B-ESC1)

公司裡最近開始投入STM32的行列

特別是在馬達控制這一段

原先站長就已經蒐集了很多的相關資料

從SDK3.0,SDK4.3,SDK5.0直到現在的SDK5.4

然而從來沒有真正使用板子去完成一次馬達調適的功能

週三(9/25)是第一次使用 B-G431B-ESC1 的開發板

這幾天試下來很有心得

過程中還好幾次跟 Boss 發生超級激烈的討論

所幸結果是甘甜的

接下來把測試過程詳實記錄在此

希望可以減少新手使用上的盲點

尤其是只靠自己摸索而沒有機會去上培訓課程的人

=============================================================

B-G431B-ESC1 是一片為無人機(Drone)開發的馬達驅動板

大小只有半張名片不到

上面密密麻麻都是SMD的零件

信號用電阻電容基本上都是0402的規格

總之是一片零件密度非常高的板子

但這片小小的板子卻存在非常強大且完整的功能

它可以用 FOC 驅動馬達

也可以用六步方波去驅動

可以用hall sensor或encoder去偵測角度

也可以 sensorless 驅動就好

由 PLL 或 Cordic 去推算角度

供應電壓從 DC8~28V

驅動電流可以高達40A

不過功能這麼強大的板子

使用手冊卻很陽春

如果沒有之前使用 STM32 其他系列 MC Workbench 的經驗

要自己摸索出正確的使用方式是有點門檻的


=============================================================

第一次進行測試先要準備幾樣東西:

0. B-G431B-ESC1 with Vcc/Gnd/U/V/W cables

1. USB_mini cable

2. BLDC motor (Any type)

3. Power Supply (12V/24V)

4. 安裝 x-cube-mcsdk 
   (預載編譯環境 MDK5 及 STM32CubeMX)


分別說明一下這幾樣東西要怎麼準備

首先要把 B-G431B-ESC1 板子上的 Vcc/Gnd/U/V/W 接點拉線出來

可以在 UM2516 這份文件上找到接點的位置

並準備一條 mini type 的 USB cable

這種 USB cable 是在 USB3 出來之前手機最常用的充電下載線

也就是如果你有過去淘汰不用的手機所留下的充電線

直接拿來用就可以了

最好是有帶磁環(磁珠)的電纜

不然就是長度在 30cm~50cm 之間的 USB cable 比較恰當

馬達可以隨意一個你正在使用的 BLDC motor

不管高壓/低壓/電流大小

只要有 BLDC motor 就可以

電源供應器(Power Supply)最好用可以調整電壓電流的

建議可以輸出0~30V/0~5A以上的較為合適 (150W以上)

前面的工作都準備完成就可以開始安裝 x-cube-mcsdk (v5.4.1)

檔案會是zip壓縮檔,大小約112MB

由於站長是 Keil C 的愛用者

因此這裡用 MDK5 的環境來做介紹

而腳位定義與 MCU 周邊功能會使用到 STM32CubeMX

所以也要先安裝好才開始進行測試


=============================================================

第一次操作 Motor Profiler 與 MC Workbench

安裝好 x-cube-mcsdk 之後

桌面會有 Motor Profiler 與 MC workbench 兩個捷徑

如果要調適馬達參數

我們要先使用 Motor Profiler 這個工具

使用前請先將 USB_mini cable 連接到 B-G431B-ESC1 開發板

將馬達三條出力線任意接上 B-G431B-ESC1 拉線出來的 U/V/W

最後將電源供應器的輸出調節在 DC12V/2A 這個條件上

並接上 Vcc/Gnd 的線

執行 Motor Profiler 會出現板子的選用

第一個出現的就是 B-G431B-ESC1

點選板子後要輸入馬達基本參數

極對數在 Motor Profiler 有提供教學

在此不多做說明

看不懂的可以留言問我

如果你完全不曉得你所使用的馬達參數

有幾個方向你可以參考看看

首先就是馬達的大小

如果比拳頭小的通常轉速很快

設定轉速條件可以 5000RPM 以上

如果比拳頭大但比兩個拳頭小

轉速條件可以設在 3000RPM 進行測試

更大的馬達通常不容易拿到

如果拿得到也通常會提供完整參數

電壓電流暫定12V/2A

這是一個最保險且不容易損壞板子與電源供應器的條件

不過如果你的馬達比大拇指還小

建議還是要調低一下電流

對低壓馬達來說,1A應該是最低限度

電流太小其實不好調適馬達

當這些條件都輸入完成後

就點選 connect 讓 Motor Profiler 與 B-G431B-ESC1 連線

連線成功就直接按 Start 進行馬達參數的調適

如果你的馬達在調適過程中完全沒有動

可以先重複調適 3~5 次

有時候是因為 USB 通訊的問題

也有可能是電腦作業系統的問題

並不是每一次連線都可以很順利的

因為馬達本來就是信號干擾源

假如你調適幾次後發現馬達都完全沒有動

可以考慮加大你的輸出電流

或是提高轉速上限

不同的轉速上限與電流峰值

會改變馬達調適的初始化開迴路驅動信號

假如動了又停住

沒辦法連續一直轉

就建議調低一下電流量

大多數的馬達在 1~2A 的電流範圍內應該都是可以調適轉起來的

只是這並不一定是馬達真正適用的參數

我們只是要先確認馬達會動的方法

如果馬達有成功連續運轉

並有慢慢減速到停止

那代表這組參數是可以用的

用 SAVE 鍵把馬達參數存起來

記住這個馬達的名字 (這裡先取名為TEST_MOTOR)

接下來在 MC workbench 中會用到

如果您想試試看馬達運轉的情況

用 PLAY 鍵進入簡易測試環境

這裡可以設定馬達緩啟動的條件

也可以測試轉速的穩定度

如果測試起來不滿意可以一直重新調適

直到跑出一組覺得還蠻順的馬達參數

但原則上只要能轉就算OK了

因為進入Workbench後還有很多細節可以調整

這裡只是先抓個馬達的基本參數

讓程式有調整的方向而已

=============================================================

進入Workbench後要點選New Project

在Inverter選單中會出現B-G431B-ESC1這片板子

稍微說明一下

官方的板子有幾種類型

第一種是 All in One 的類型 (主控與驅動做在同一片板子上)

這一類會放置在 Inverter 中

第二種是組合套件且有附馬達的類型 (主控板與驅動板分開)

這一類會放置在 MC kit 中

第三種是組合套件沒有附馬達的類型 (主控板與驅動板分開)

這一類會放置在 Power & Control 中

而我們所使用的B-G431B-ESC1是All in One的板子

所以在Inverter中可以找到

不管你選用哪一種類型的板子

在頁面的最下方要記得選擇剛剛你所調適好的馬達

也就是選 TEST_MOTOR (使用你剛剛存起來的名字)

再來就讓 Workbench 自動幫你建立專案了

=============================================================

專案建立之後要做的事很簡單

如果你想先試試看馬達的動作

而你的 B-G431B-ESC1板子從剛剛調適之後就一直沒有拔除USB cable的話

可以 open Monitor 進入通訊調適介面

選擇 B-G431B-ESC1 的VCP (例如 COM 3)

執行Connect動作後便可以對板子連線操作

在Basic畫面中可以啟動馬達、停止馬達、改變馬達轉速、馬達正反轉

在Advanced畫面中可以調整馬達的PID參數、緩啟動設定

在Registers畫面中更可以看到所有馬達在運行中的參數變化

如果現在馬達的運轉方式是你所滿意的條件

便可以回到前一個畫面將程式碼 Generation

=============================================================

使用 Generation 功能時需要先建立專案名稱 (副檔名會是.stmcx)

然後會要求指定編譯軟體

除了常見的 Keil C 、IAR C

也支援 SW4 以及 CubeIDE

假如你跟我一樣都習慣使用 Keil C 或 IAR C

也不用刻意要改用官方提供的 SW4 或 CubeIDE

因為實測從Keil C轉出來的Code與CubeIDE所轉出來的Code

程式空間(Code size)差了將近一倍

如果Keil C轉出來是35KB好了

CubeIDE轉出來差不多是 68KB

但奇怪的是

兩個檔案資料夾是Keil C的專案夾比較占空間

而且編譯時間比CubeIDE長了不只一倍

我猜是FOC運算函式庫在Keil C有用特別的硬體加速函式

讓程式碼大幅縮小

可是因為不是標準庫的編譯方式

導致時間上變長了

如果知道這一段怎麼處理的

應該也可以在CubeIDE上做到同樣的效果

不過那就是以後才要研究的新目標

當下還是先能夠調好馬達動作比較重要

=============================================================

產生程式碼之後還會跳進CubeMX再確認一次所有的IO設定

如果你有個人想做的額外動作

比方說把預留的Hall Sensor Port拿來當做Display的控制線

因為Sensorless驅動時不需要用 Hall Sensor Port

所以在此可以先做一個小小的變化

然後再GenCode一次

轉出來的專案可以直接下載到 B-G431B-ESC1

然後如果你按照預設的程式都沒有改變

下載後按一下板子上的按鍵

馬達就自己轉起來了

當然也可以用VCP跟他連線

只要打開Workbench中剛剛建立好的專案.stmcx

進入Monitor中就可以連線操作馬達了

不過這時候的連線跟剛剛調適時的連線有點不太一樣唷!

剛剛調適時的連線

是Motor Profile預載一個空馬達參數的架構

透過Motor Profile的調適流程將馬達參數計算出來

所有的參數都是可以即時修正的

但是只要斷電重來

所有的參數就遺失了

必須重新調適

然而經過燒錄後的程式

是將調適好的參數當成預設參數填入MCU中

每次重新上電就會自動執行這組參數

某些板子還支援兩顆馬達同時運作

此時就是放入兩組不同的馬達參數

以同樣的FOC架構去運行

假如你想要一片板子可以同時讓很多不一樣的馬達使用

當然也可以自己將各組馬達參數寫在程式中

以IO切換或通訊更新的方式來切換馬達參數

這樣就可以讓一片板子運行很多不一樣的馬達

但前提要板子的驅動能力是可以應付的

也就是瓦數相近且電壓範圍也相近的馬達才能這樣用

畢竟一顆馬達會用到的參數很多

如有任一參數引用錯誤的話

是非常有可能發生災難的

=============================================================

上面的調適流程如果夠熟悉

而板子的驅動能力又跟馬達有匹配的話

基本上只要10分鐘不到就可以讓一個馬達順利運轉起來

不過調適馬達並不是只要會轉

還要加載測試及各種意外狀況的模擬

這些就要額外多花時間去調整了

但這套工具真的大幅縮短了馬達前期調適的時間

讓馬達驅動可以快速進入應用階段的測試

對電機工程師來說真的是一個很大的福音

重點是價格還不貴

軟體又通通在官網就可以下載得到

強烈推薦給大家試用看看唷~~

2019年9月1日 星期日

STM32CubeMX之串列中斷--STM32F205RBT6在MDK5的應用範例

站長在過去的文章中

有大量提及串列通訊的概念

不論是在機械手臂的控制篇或是 Modbus 的介紹中

而在 STM32 環境裡只有寫法變成了函式庫的呼叫用法

其他的概念都一樣

只要瞭解函式庫所代表的動作含意

寫起來就跟以往的串列中斷沒甚麼兩樣

延續上一個程式

我們開啟 Hello.ioc 將 Connectivity -> USART3 中

Configuration -> NVIC Settings 的 Enable 勾選

重新按下右上角的 GENERATE CODE

此時串列中斷的功能就被開啟了

而且在 GENERATE CODE 之後

我們可以發現原來寫在 USER CODE 裡的程式碼都被保留下來

並不會被新產生的程式碼所覆蓋清除

如此我們可以放心地將板子上的功能一一慢慢驗證

當問題發生時也容易釐清是哪一個新加入的功能導致誤動作

儘量不要囫圇吞棗一下子把所有的功能都打開

尤其在面對不熟悉的介面或很多周邊整合應用時

常常會發生某個功能設定好就導致另一個功能異常的情況

特別是周邊功能有優先權衝突的時候

慢慢加入功能可以快速且有效地釐清問題點

建議大家可以用這樣的方式進行程式撰寫

==========================================================

/* USER CODE BEGIN PV */
uint8_t Enter[] = { 0x0d, 0x0a };
uint8_t Hello[] = { "Hello World !!!" };

uint8_t uart3_read_buffers[10];
uint8_t uart3_conv;
uint8_t uart3_read_cnt=0;
/* USER CODE END PV */

/* USER CODE BEGIN 2 */
HAL_UART_Transmit (&huart3, Enter, sizeof(Enter), 0xffff);
HAL_UART_Transmit (&huart3, Hello, sizeof(Hello)-1, 0xffff);
HAL_UART_Transmit (&huart3, Enter, sizeof(Enter), 0xffff);
HAL_Delay(1000);
HAL_UART_Receive_IT (&huart3,&uart3_conv,1);
/* USER CODE END 2 */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  UNUSED(huart);
  uart3_read_buffers[uart3_read_cnt]=uart3_conv;
  uart3_read_cnt++;
  HAL_UART_Receive_IT (&huart3,&uart3_conv,1);
  if (uart3_read_cnt>=10 || uart3_conv==0x0a) 
  {
    HAL_UART_Transmit_IT (&huart3,uart3_read_buffers,uart3_read_cnt);
    uart3_read_cnt=0;
  }
}
/* USER CODE END 4 */

上一篇文章利用 while 迴圈的輪詢

讓 UART3 不斷送出 Hello World !!! 的資料

這一次我們將 Hello World !!! 搬到 /* USER CODE BEGIN 2 */ 的位置

清空原來 while 迴圈裡的程式 (/* USER CODE BEGIN 3 */的位置)

並加入串列接收的中斷功能 HAL_UART_Receive_IT (&huart3,&uart3_conv,1)

這是啟動從 UART3_RX 收到一個 Byte 的資料後會發生中斷的功能

收到的資料會放在 uart3_conv 這個變數上

請注意這個函式所接受的資料參數是指標型態

因此呼叫的時候我寫成 &uart3_conv

就是把收到的資料放在 uart3_conv 的位址上

任何變數前面加上 & 的符號就是代表該變數在程式裡的位址 (指標的概念)

當中斷發生時,系統會自動執行

HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 這個函式

我把函式放在 /* USER CODE BEGIN 4 */ 的位置

接下來的程式裡要傳達幾個概念:

第一個是 UNUSED(huart)

這是避免編譯器出現未使用警告

詳細的發生原因可以參考這篇文章的說明

第二個是接收資料並重啟中斷的寫法

uart3_conv這個變數會儲存最新一個 Byte 的串列資料

在下一個 Byte 進來之前

我們必須將裡面的資料搬移到資料陣列中 uart3_read_buffers[]

等待接收到滿足條件的資料後才進行資料分析

並且重新啟動串列接收中斷

才不會漏掉即將進來的下一個 Byte 資料

第三個是判斷資料與回傳資料的時機

這個範例是將儲存在資料陣列中的資料回傳

當作是滿足指令條件的回應動作

而指令就是收到換行符號

然而資料陣列的長度只有 10 Bytes

超過陣列長度的資料除非覆蓋掉原來的資料繼續儲存

不然就會產生誤動作 (更改到其他變數用記憶體的資料)

因此程式才會在滿足陣列長度時先回傳資料

並將計數歸零以重新接收新一輪的資料

直到有新的換行符號出現為止

而且回傳的函式也用了中斷寫法

當傳送完成後系統會先進到

HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) 這個函式中

如果你有需要判斷傳送是否完成

可以在 HAL_UART_TxCpltCallback 中加入判斷式及對應動作

==========================================================

使用中斷寫法的好處

就是系統不會一直等待串列動作完成

而把收發資料的動作交給串列周邊自己完成

等收發完成後系統再接手

而等待收發完成的這段時間

系統可以繼續做其他的事

比方說繼續量測電壓

繼續驅動馬達運轉......

諸如此類

不過

即便以中斷寫法來寫

進入中斷函式到離開還是需要一些時間

這段時間還是算占用中斷資源

如果在這段時間有其他中斷進來

就會排在後面或直接被捨棄掉

利用 AccessPort 做了一下實驗

將六組帶有換行符號的字串不間斷地連續送給 MCU

並不是每一次都可以六組完整地回傳給 AccessPort

最差的情況只回傳了三組

換句話說

串列還是要考慮進入中斷後重新啟動所花費的時間

收與發還是要有一定的時間間隔

才能確保資料的收發不會漏掉

==========================================================

為了證明收與發互搶中斷資源的問題

特別將資料陣列的長度改成 100

並且讓收與發的字串長度增加到了 70~80 Bytes

再用 AccessPort 連續發送六組資料

這次發現不管重複發送多少次

六組資料都完整地被回傳

當回傳的中斷執行間隔被拉長

收發的穩定度就提高了

因為發送資料的頻率降低

占用中斷的時間也相對變少

也不容易發生重複排程而被捨棄的問題

實驗後才發現

原來不是資料送得少才穩定

反而是送得多才穩定

送得多代表大部分的動作交給串列周邊處理

真正占用到 MCU 的時間變少了

系統才有充裕的時間處理更多的事

這也才是使用中斷的精華所在

希望這篇文章能對您有些幫助

有任何問題或是我有說錯的地方

也請不吝指教

接下來要引入 DMA 的用法

也請繼續期待!

2019年8月28日 星期三

Hello World--STM32F205RBT6在MDK5的應用範例

上一篇文章提到

在 CubeMX 可以產生多種編譯環境中常見的程式碼

其中包含 IAR 的 EWARM V7/V8

Keil 的 MDK-ARM V4/V5

還有自家最新推出的 CubeIDE

與第三方(AC6)合作的 SW4STM32

這些編譯環境都可以被 CubeMX 所支援

不過我本身對 MDK 的環境比較熟悉

所以才會以 MDK5 作為範例

如果有機會

建議可以嘗試一下 CubeIDE 或 SW4STM32

官方資源與開源環境是新時代的趨勢

自由度越高的環境才能被更多的使用者接受

等我熟悉過 CubeIDE 及 SW4STM32 後再來跟大家分享

暫時先看看 MDK5 的範例吧 (以官方試用版的空間限制就能完成的專案)

==========================================================

由 CubeMX 所產生的 MDK5 程式碼會包含以下幾個資料夾:

1. Drivers:其中包括 CMSIS (Cortex MCU Software Interface Standard)
及 STM32F2xx_HAL_Driver (STM 官方 HAL 庫)

2. Inc:

程式所需的 include 檔

3. MDK-ARM:

包含專案捷徑及除錯所需的連結檔、燒錄檔

4. Src:

主要程式的原始碼 (使用者修改專用)


然後還有一個 Hello.ioc 的 CubeMX 專用 IO 編輯檔

剛剛產生的檔案中

MDK-ARM資料夾內的資料應該都是空的

因為專案本身還沒經過編譯

所以連結檔與燒錄檔都尚未產生

等第一次編譯過後就會有對應的檔案出現

今天的目標是要完成 Hello World 的任務

所以先進入MDK-ARM的資料夾中

由 Hello.uvprojx 的專案檔開啟專案

這是站長習慣的開啟方式

你也可以先打開 MDK5 由 Project -> Open Project 的方式來開啟

因為是第一次開啟專案

所以 Project 應該還沒把專案列入最近清單中

等編譯完成後就可以由最近清單中去開啟專案

另外

進入專案後第一件要確認的就是燒錄環境的設定

如果您使用的是 ST LINK 當作燒錄的工具

那麼就可以忽略接下來的步驟

不過建議還是檢查一下比較保險

我所使用的是 MDK5 專用的 ULINK2

與專案所建立的 ST LINK 是不一樣的工具

所以要先到 Flash -> Configure Falsh Tools... 中

將 Debug 欄位裡的工具更改為 ULINK2

您可以依照自己所使用的工具進行修改

別忘了要替燒錄工具的韌體進行更新

免得不支援選用的 MCU 就 GG 了

==========================================================

要完成 Hello World 的任務

有幾個重要的觀念要先建立

一般來說

周邊功能有三種方式可以呼叫

第一種是用輪詢

第二種是用中斷

第三種是DMA

這個範例會先以輪詢的方式進行撰寫

先驗證IO動作是正確的

之後再嘗試中斷與DMA的寫法

其次

標準 C 語言有內建通訊的函式 printf ()

要使用這個功能必須引用 <stdio.h> 這個開頭檔

否則編譯過程中會發生語法錯誤

由於通訊功能相關的程式碼放在 usart.c 當中

所以首先要改寫的程式便從 usart.c 開始

==========================================================

/* USER CODE BEGIN 0 */

#include <stdio.h>

/* USER CODE END 0 */

/* USER CODE BEGIN 1 */

#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}

/* USER CODE END 1 */

在 usart.c 中找到 /* USER CODE BEGIN 0 */ 與 /* USER CODE BEGIN 1 */ 的位置

加入上方的程式碼

因為我們接下來會引用 printf 函式

編譯時會檢查編譯環境的設定

所以定義了編譯環境所必須的參數

而 HAL_UART_Transmit 函式則是 HAL 庫內建功能

在 stm32f2xx_hal_uart.c 中可以找到

功能是將 printf 所要丟出的字串一個一個 Byte 傳送出去

==========================================================

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN 3 */
printf("\r\n Hello World !! \r\n");
HAL_Delay(1000);
  }
/* USER CODE END 3 */

接下來到主程式 main.c 中

找到 /* USER CODE BEGIN Includes */ 及 /* USER CODE BEGIN 3 */

把上面的程式碼加入

其中 HAL_Dealy 約是每個計數 1mS 的延遲 (在 stm32f2xx_hal.c 中)

設定1000為1秒鐘延遲的意思

然後點擊 Rebuild 鍵先進行第一次編譯動作

之後就等待 MDK5 編譯完成

第一次編譯通常會花上一些時間

完成後執行 Load 將程式燒錄到 MCU 中

如果前面的燒錄工具有設定正確的話

應該很快就可以燒錄(下載)成功

接上 USB<->UART 工具或任何可以觀看 UART 通訊資料的工具

你就可以看到 Hello World !! 字樣

==========================================================

如果你不是很習慣作業系統的寫法

不想使用 printf 來傳送資料

那可以怎麼修改呢?

/* USER CODE BEGIN PV */
uint8_t Enter[] = { 0x0d, 0x0a };
uint8_t Hello[] = { "Hello World !!!" };
/* USER CODE END PV */

/* USER CODE BEGIN 3 */
HAL_UART_Transmit (&huart3, Enter, sizeof(Enter), 0xffff);
HAL_UART_Transmit (&huart3, Hello, sizeof(Hello)-1, 0xffff);
HAL_UART_Transmit (&huart3, Enter, sizeof(Enter), 0xffff);
HAL_Delay(1000);
  }
/* USER CODE END 3 */

回歸到單晶片的概念

就是找到傳送的函式

把要丟出去的字串定義好丟出去就可以了

所以可以不要修改 usart.c 中的內容

只在 main.c 中找到 /* USER CODE BEGIN PV */ 及 /* USER CODE BEGIN 3 */

將上面的程式碼寫入對應的位置上

一樣可以看到 Hello World !!! 的字樣

其中

由於宣告為字串的矩陣會多帶一個空字串

所以使用sizeof()這個功能時要將空字串的計數減掉 [sizeof(Hello)-1]

不然會在通訊中多看到一個 0x00 的碼躲在 Hello World !!!後面

==========================================================

最後要提一下 CubeMX 所要帶給我們的改變與新思維:

第一

不要再以硬體底層的概念來看單晶片程式

因為現在的單晶片都不再是以往簡單幾個周邊功能而已

各個周邊之間的關聯性與複雜度都今非昔比

建立以系統觀的思維來看待程式

嘗試以作業系統的寫法來修正以往的撰寫習慣

可以提高程式的可攜性與移植性

避開重複開發以縮短專案完成的時間

第二

我們不是單晶片大廠的員工

也不是設計單晶片的設計師

不應該為單晶片的驅動與除錯負責

這應該是單晶片大廠所要克服的功課

在高度分工的科技時代

如果還要工程師從頭到尾把晶片廠的問題一一克服才開始開發專案

那開發的進度鐵定落後到天荒地老

並不是我們不具備解決問題的能力

也不是我們缺乏學習的動力與毅力

而是在商言商--時間就是金錢

很多舊時代的大廠還停留在工程師就是要解決所有的開發問題

而忽略分工的責任劃分與時間、專案管理的問題

甚至把問題都怪罪到研發工程師的身上

認為他們程度差且懶惰又不負責任

這是非常落伍且不公平的

第三

工欲善其事,必先利其器

如果有更好的工具可以用

就不要因為習慣了舊工具就排斥接觸新工具

每個學習都有陣痛期

但如果陣痛可以帶來脫胎換骨的大提升

那為何不痛一下就好?

而要一直忍受效率不好的開發工具

讓自己的競爭力越來越不好呢?

人本來就是活到老學到老

不是嗎?

希望你會喜歡這篇文章的介紹

下一篇我們要探討一下中斷與DMA的用法

敬請繼續期待

2019年8月27日 星期二

STM32CubeMX產生專案碼的步驟--STM32F205RBT6在MDK5的應用範例

好久不見,大家最近過得好嗎?

這是理科太太最愛用的開場白

我覺得很實用就搬來借用一下

很長一段時間沒有更新與單晶片有關的訊息

並不是已經脫離了單晶片

而是鑽得更深入後發現了新大陸

在眾說紛紜、無所適從的超大量文件中

找到了最適合自己理解的方法

並打算一系列整理好記錄在這裡

進入主題

今天要介紹的是STM32所推出的STM32CubeMX工具(以下簡稱CubeMX)

目前官方最新版本為5.3.0

如果用過以前4.x的版本

會發現新版本的畫面變得很華麗

畫面分頁的方式讓閱讀更直觀也更簡潔

但習慣了舊畫面的使用者可能需要一點時間適應

因為版面的編排位置有不小的改變

內容上則差不多

==========================================================

開啟CubeMX

第一個看到的是歡迎畫面

正中間的深藍色方框是開啟新專案的選項

左邊則是開啟就專案的選項


右邊則是更新與設定的選項


接下來會先示範一個建立新專案的方法

這是初學者入門時最需要的部分

以往建立新專案的方法

要先到官方下載在編譯環境中適用的MCU韌體封包 (驅動程式碼、固件庫)

然後將整組設定引入編譯環境中

再自己一個一個將需要的功能

從移入的驅動程式碼中找出來設定

只要漏掉一個細節就會導致程式完全不動

而且還找不到病因,欲哭無淚

入門最怕遇到冗長難懂的文字設定流程

特別是因為理解偏差 (語文能力不好) 而產生的誤設定

CubeMX直觀的圖形操作可以省下不少麻煩

往下做你就會發現他的魅力

==========================================================


首先在歡迎畫面的正中間找到 Start My Project from MCU

點選其下方的 ACCESS TO MCU SELECTOR (紅色方框)

進入MCU選單中

在選單中輸入 STM32F205RB 這個 MCU 編號

右下方的畫面會出現與此編號相關的所有MCU選項

如果只輸入 STM32F2 則會出現整個 F2 系列的 MCU

這個選項裡會列出MCU的參考價格、對應的官方開發板、包裝、......

可以初步先確認選用的MCU是不是自己想要的

若點選需要的MCU後 (如STM32F205RB)

右上方則會出現更多與 MCU 相關的訊息


第一個出現的是MCU的基本規格描述 (Features)

和官網上的訊息一致

如果定期更新CubeMX的話

可以隨時看到第一手的MCU資訊



隔壁一欄Block Diagram則是MCU的功能方塊圖

在這個頁面可以快速檢閱 MCU的所有功能



再隔壁一欄Docs & Resources可以看到與該 MCU 相關的所有參考文件

直接點選要看的資料 (如點選RM0033)

就會連結到對應文件的網址直接下載回來


像這樣

連結到對應的文件後就開始下載

下載成功會直接開啟



==========================================================

回到原選單中雙擊 STM32F205RB 這個 MCU 編號

CubeMX會自動進入圖形化MCU設定畫面


出現的畫面是MCU完整腳位的 Pinout

在這裡要先確認一下MCU的包裝有沒有選對

同一個MCU編號可能會有不同的包裝

而不同的包裝可能存在腳位設定上的些許差異

如果發現包裝不對可以在上方的File選單中重新建立New Project

此時可以開始對 MCU的腳位及初始條件做規劃

第一件要做的是點選 System Core進入sys設定燒錄與除錯的方式


設定的方式很簡單也很直觀

就是點選sys

CubeMX就會自動跳出設定視窗


接著在 Debug 中把 Disable 改成 Serisl Wire



這樣就算設定完成了


設定好功能後會在對應的腳位上變成綠色

如果腳位是黃色代表選定的腳位功能還未開啟

要到對應的功能中把需要的設定補上

若是覺得設定視窗很佔畫面

可以把設定視窗收起來

方便檢視MCU腳位並設定

在設定視窗的右上角有兩個三角形的收放功能

點選紅色框框中的三角形就可以收起設定視窗



像這樣

已經設定好的腳位就會以綠色呈現

此時可以繼續對其他功能進行設定

==========================================================

緊接著要開始設定系統的時脈 RCC

由於我的應用是要使用外部石英晶體當成振盪源

所以要在High Speed Clock (HSC) 中選擇 Cyctal / Ceramic Resistor


選擇好之後對應的振盪腳位也會變成綠色



不過接下來要做的並不是繼續在設定視窗中點選功能

而是移到隔壁欄位 Clock Configuration 中去設定系統時脈


在這裡可以直接看到整個MCU所有跟時脈設定有關的方塊圖

要改變的設定直接在欄位中點選輸入就好

輸入的順序是由左而右,由上至下

由於剛剛已經將HSC的外部振盪腳位設定好了

所以在 Clock Configuration 中外部振盪器是以藍色反白呈現

這裡可以輸入實際應用的石英晶體時脈 (如25, 16, 12, 8......)

預設為25MHz





接下來由左到右我依序修改了一些參數來滿足板子的時脈需求

如果單純使用外部振盪器來當系統時脈

那麼設定到頂天也就25MHZ

要跑上120MHz的系統時脈

得靠內部PLLCLK將HSC倍頻上去

所以我將PLLCLK的振盪源指定為HSC

經過除頻(/25) 倍頻(x240) 除頻 (/2) 的設定後

進入系統的振盪時脈變成120MHz

然而周邊匯流排的時脈跟不上系統的時脈 (APB1:30MHz / APB2: 60MHz)

所以分配給匯流排的時脈還要經過(/4) (/2)的除頻過程

點選好就設定完成了

==========================================================

系統時脈設定好

加個周邊功能來試試

一般來說都會加GPIO或"Hello World"的測試 (UART功能)

這裡以UART3的設定作為範例


我所使用的板子

規劃了PC10與PC11當作UART3的功能腳

因此直接在MCU右上方的PC10與PC11點一下

會出現功能選單

選擇USART3_RX與USART3_TX後

MCU的腳位會變成黃色


為什麼是黃色?

前面的文章有提到是功能未啟用

所以到左邊的 Connectivity 選單中找到 USART3 點一下




接著在 Mode 中 把 Disable 改成 Asynchronous




這樣就把UART3的功能打開並對應到PC10與PC11的腳位上

另外一種方法是先在功能選單中把USART3的功能模式設定好

MCU會跳出預設對應的 IO 腳

以本專案為例

選擇USART3之後會出現PB10與PB11兩隻腳

之後再到MCU的PC10與PC11點選USART3_RX / USART3_TX

一樣可以把 IO 正確定義到需要的腳位上

==========================================================

到此為止

我們把MCU要運作的最基本設定都設好了

要開始產生程式碼的專案檔了


將畫面切換到 Project Manager 頁面上

這裡就是要產生程式碼專案前的設定

左邊可以看到三個選單

第一個選單是Project

第二個選單是Code Generator


第三個選單是Advanced Settings




在Project選單中

我們要先給專案一個名字

這裡設為Hello

專案資料夾要擺放的路徑設在桌面上 (可利用Browse鍵改變路徑)

路徑產生後會將專案名稱當作資料夾名稱放在桌面 (指定的路徑) 上

最重要的

就是不要漏掉你所使用的編譯環境設定 (設為 MDK-ARM V5)


切換到下一個 Code Generator 選單中

把紅色方框中的選項勾選

這個功能會把所有MCU的周邊功能獨立成一個成對的.c與.h檔

將來較容易修正程式且方便閱讀

建議要勾選

不然產生的周邊程式碼會全部放在主程式(main.c)中

程式看起來會很累

而 Advanced Settings 選單中會提示你現在周邊功能開啟的狀況

你可以根據需求做一下調整

這裡因為不做調整就直接跳過

做好上面所有的設定後就可以直接將右上角的 GENERATE CODE 鍵點一下


接下來會等待一小段時間

如果您所開啟的功能比較多

產生程式碼的時間也會比較久

專案建立好之後會跳出一個對話視窗

您可以點選開啟資料夾或開啟專案

若您選擇開啟資料夾

就會看到熟悉的MDK5程式碼結構


裡面多了一個以前沒見過的東西 Hello.ioc

這個檔案是CubeMX專用的IO設定檔

你剛剛所有的設定都儲存在這個檔案裡

只要點選Hello.ioc就可以將剛剛的設定呼叫出來

重點是

你可以隨時任意更改這裡的功能設定

並且重新產生新的程式碼

只要在剛剛的Code Generator中有設定Keep User Code when re-generating (預設選項)

所有自己寫好的程式碼都不會被修改

只會更動與功能設定有關的程式碼

==========================================================

CubeMX可以快速配置好一片新板子所需要的所有功能

如果你對板子的功能很熟悉

那麼使用CubeMX便能加速你開發板子的速度

因為CubeMX再好用

也要自己先了解MCU的功能及用法

CubeMX只是充當索引的角色

此外

建立好專案不代表程式已經可以動作了

要say Hello還是得靠自己key程式

下一篇文章要延續這個專案

將MDK5的程式碼結構介紹一下

敬請期待

2019年3月28日 星期四

充電一下 -- 好用的免費通訊軟體 AccessPort & SerialPlot

好久沒上來PO文了
今天來跟大家分享一下好用的通訊軟體

如果之前有在follow機械手臂的朋友們
應該都曉得[AccessPort]這套軟體
如今最新版本已經更新到1.37
使用的方式跟以往都相同
在此便不多加贅述


歡迎大家繼續支持

接下來所要介紹的[SerialPlot]
其實是在2015年就已經問世的通訊軟體
經過兩年時間的調整
在2017年推出了最新版本 V0.10.0


站長第一次接觸是在v0.8.1的版本
當時為了幫通訊回傳的資料繪製曲線
早期自己用VB6寫的繪圖程式
因為擴充性不足且運作效率不佳
後來就上網找現成的通訊繪圖軟體

然而第一次安裝的經驗並不好
因為安裝到一半就說安裝失敗
出現"path too long installer unable to modify path" 這樣的訊息

不管是使用系統管理員身分安裝
或是一般使用者身分安裝
甚至將檔案改到 c:\ 完全沒有資料夾跟中文檔名問題的情況下
也依舊安裝失敗

好事多磨
後來才發現這樣的失敗訊息只是因為建立捷徑檔的異常
原始程式的執行檔已經安裝在 program files\serialplot\bin底下
直接到該資料夾內點選serialplot.exe檔就可以運作了
當下真是三條線......

如果您安裝完也發生與站長同樣的問題
記得直接到資料夾底下找執行檔就好
直接點擊執行檔就可以使用了

使用的方式很直觀
但是要先理解一下輸入的格式

binary

如果您所接收到數值是屬於二進位格式的
單一變數比較好確認
只要定義好變數型態(signed/unsigned)(8/16/32 bits)
開啟對應的ComPort
serialplot就會開始自動繪製曲線
如果是多組變數回傳
請確認回傳的變數型態統一
並且依序輪傳
此時在serialplot中設定好變數的組數(channels)
就會自動分類並繪製各變數的曲線
但是通訊過程有漏掉資料筆數
就會造成整個曲線繪製的錯亂
此問題在這個模式下無解

ASCII

既然binary模式無解
當然就會有其他對應的模式產生
ASCII就相對簡單多了
透過逗號決定各組參數
換行符號決定資料筆數
也就是第一行代表所有變數的第一筆
第二行代表所有變數的第二筆
依此類推
不過如果回傳時漏掉逗號
還是可能會有爆點的出現
但應該會收斂在一點上
而不會整個曲線都混亂
在這個模式會自動分析數值的組數
不需自己設定(由逗點數決定)

Data Frame

如果您的資料必須是二進位格式
又想要不讓曲線因漏資料而錯亂
那麼你可以考慮用第三種模式
他可以自行定義資料流啟始的編碼
並且有checksum的機制來判斷資料是否缺漏
應該可以某種程度上避開不必要的錯誤
維持曲線的完整度


有了這個軟體
就可以輕鬆從曲線上看到
溫度變化
轉速變化
電壓電流變化
位置變化
亮度變化
......
各種你覺得從曲線圖上可以快速分析的資料
都可以透過這個軟體即時觀看
簡單說就是一台串列通訊示波器的概念
有興趣的可以試試看唷~~~