2017年8月8日 星期二

stm32f4 使用計時器計時 1ms

stm32f4 使用計時器計時 1ms

可以使用官方範例程式內的 Examples\TIM\TIM_TimeBase 修改
預設是 delay 1s 修改一下參數 Period 除以 1000 即是 1ms
初始化計時器
void timers_init()
{
    uint32_t time_c = 10000;
    uwPrescalerValue = (uint32_t)((SystemCoreClock / 2) / 10000) - 1;
    TimHandle.Instance = TIMx;
    TimHandle.Init.Period = 10000/1000 - 1 ;
    TimHandle.Init.Prescaler         = uwPrescalerValue;
    TimHandle.Init.ClockDivision     = 0;
    TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
    TimHandle.Init.RepetitionCounter = 0;

    if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
    {
        Error_Handler();
    }

    if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
    {
        Error_Handler();
    }
}
這裡這樣設置就可以了,再來它會自動每 1ms 呼叫 HAL_TIM_PeriodElapsedCallback() 這個函式,這個函式這樣寫
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    static int timer1 = 0;
    static int timer2 = 0;
    ++timer1;
    ++timer2;

    if(timer1 == 1000) {
        BSP_LED_Toggle(LED1);
        timer1 = 0;
    }

    if(timer2 == 500) {
        BSP_LED_Toggle(LED2);
        timer2 = 0;
    }
}
即可用不同頻率閃爍LED了,我不確定中斷程序會不會等這個函式執行完畢;建議用一個全域變數當flag,讓計時器激活他,然後由主函式內的 while 統一控管來處理,不然可能會卡住導致延遲。

Keil uVision 5 查看變數出現 無法查看

Keil uVision 5 查看變數出現 無法查看

因為預設編譯器是優化全開 -O3 某些變數被優化掉就看不到了,暫時先關閉優化就好了
先進入專案選項內
選擇 -O0
再來須要全部重新編譯 F7,需要花點時間,編譯完畢之後使用
F10 (跳過fun) 或 F11(行執行) 來跑程式跑到你要的位置
你可以把滑鼠移動到變數上查看,也可以從右下角查看區域變數。

2017年8月6日 星期日

如何改 Windows 10 桌面右鍵的選單內容的快捷鍵

如何改 Windows 10 桌面右鍵的選單內容的快捷鍵

先按一下開始直接打字搜尋 regedit 進入登錄檔編輯器
接著在上面的路徑輸入,舊版的沒有上面那一條好像自己慢慢點進去
電腦\HKEY_CLASSES_ROOT\Local Settings\MuiCache
再來一路開進去
這邊以 VS 為例,點兩下進去把
在 Visual Studio 中開啟(&V),後面的V改成你要的任意快捷鍵就可以了。

2017年7月31日 星期一

Markdown HackMD Github 同一頁文內跳轉

Markdown HackMD Github 同一頁文內跳轉

使用超連結跳轉即可

HackMD

在 HackMD 內大標題中標題小標題都會自己有一個標籤
比如說一個大標籤
# 第一章
## 第一節
相對應的跳轉方式就是
- [第一章](#第一章)
- [第一節](#第一節)

Github

這個就沒有Markdown自己擴展的連結,只能自己用html補
<h2 id="First">第一章</h2>
相對應的跳轉方式就是
- [第一章](#First)

STM32F469I GPIO 基本的閃爍控制

STM32F469I GPIO 基本的閃爍控制

板子上現成的 LED 與按鈕對應的 GPIO 腳位

LED1 G6
LED2 D4
LED3 D5
LED4 K3
按键 A0

函式解說

延遲函式,這個內建沒有我們自己弄一個
void delay(){
  int i;
  for(i=0; i<0xffffff; ++i);
}
如果需要精準的時間延遲可以參考這一篇站內連結
STM32 (F469I) 延遲時間 如何精準的計算

初始化

HAL_Init();
BSP_LED_Init(LED1);
這裡的LED1是對應到這張板子的正面的LED1

使用函式

關燈
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_PIN , GPIO_PIN_RESET);
開燈
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_PIN , GPIO_PIN_SET);

範例代碼

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  BSP_LED_Init(LED1);

  while(1)
  {
    delay();
    HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_PIN , GPIO_PIN_RESET);
    delay();
    HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_PIN , GPIO_PIN_SET);
  }
}

詳細代碼

如果不用內建函式LED1的字樣的話完整的打法是這樣
下面的範例是 B4 ,第一行就是改成4,第二行與第三行的 GPIO 後面改為B
  uint16_t pin = GPIO_PIN_4;
  GPIO_TypeDef* port = GPIOB;
  __HAL_RCC_GPIOB_CLK_ENABLE();

  GPIO_InitTypeDef  GPIO_InitStruct;
  GPIO_InitStruct.Pin = pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
  HAL_GPIO_Init(port, &GPIO_InitStruct);
  HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET);

GPIO所有腳位的位置

查看手冊 STM32F469 Discovery user manual.pdf 這一份文件內的資料
第17頁與18頁有提到對應MCU那些腳位
背板腳位 實際腳位
D15 PB8
D14 PB9
D13 PD3
D12 PB14
D11 PB15
D10 PH6
D9 PA7
D8 PG10
D7 PG11
D6 PA6
D5 PA2
D4 PG12
D3 PA1
D2 PG13
D1 PG14
D0 PG9

參考

按鈕控制

參考

STM32 (F469I) 延遲時間 ms us 如何精準的計算

STM32 (F469I) 延遲時間 如何精準的計算

如何利用系統內的時間 SysTick 來延遲 STM32 下面是一個示範的例子。
時脈的設定在函式內,這裡示範的時脈是 180Mhz,你可以從官方的範例代碼,隨便一個應該都有,可以看到註解會明顯地寫著 180Hhz 等字樣。
這篇介紹的是比較簡單的delay方式,但這會導致計時中板子CPU停機不工作,如果需要多個LED不同頻率閃爍藥用中斷計時比較好,參考站內連結stm32f4 使用計時器計時 1ms

初始化系統時間函式

SystemClock_Config();

調用系統函式

HAL_Delay(1000);

自訂函式

如果需要1us就把乘以1000給拿掉就可以了。
/*****************************************************************
Name : 毫秒延遲
Date : 2017/07/31
By   : CharlotteHonG
Final: 2017/07/31
*****************************************************************/
void delay_ms_core(uint32_t n) {
  uint32_t clk = 180;               // CPU 180MHz
  uint32_t ticks = time_ms * clk * 1000;  // time is ms
  uint32_t told = SysTick->VAL;
  uint32_t tnow = told;
  uint32_t tcnt = 0;
  for(; tcnt<ticks; tnow=SysTick->VAL)
  {
    if(tnow != told) {
      if(tnow < told) {
        tcnt += told - tnow;
      } else { 
        tcnt += SysTick->LOAD-tnow + told;
      } told = tnow;
    }
  }
}
搞得這麼麻煩是為了避開益位的問題
SysTick 是一個倒數的計時器,歸零之後會從SysTick->LOAD 重新開始倒數,一般來說這個數值會是 SystemCoreClock 我的板子是 16M。
這些數值在執行 HAL_Init(); 的時候會幫你設置好,你也可以從這個函式按F12慢慢追上去就可以追到這些數據了。
if(tnow != told) 是為了確保你的累加量總是小於 16M,不然如果益位超過2次你就沒辦法計算到底是多少了。每次變動後 told = tnow; 重新計算變量。
if(tnow != told) 是一般正常情況就是相減就可以得到時間變量了
else 是益位後的處理,大概是這麼算的已知總長是16M,當時間為 10(told) 被記錄到,經過一段時間變成15M(tnow),要計算其變量就是 16M - 15M(tnow) +10(told)。
就是10歸零之後又減少1M的意思了。

時間常數超出範圍

使用的時候要注意不能設太大,否則ticks可能會相乘出來會超過參數上的 uint32_t 的最大值,處理方式簡單再加一層 for 迴圈處理,依此類推自己加大時間單位。
void delay_ms(uint32_t t) {
  const uint32_t sec = 1000;
  for(; t>=sec; t-=sec) {
    delay_ms_core(sec);
  } delay_ms_core(t);
}


參考

2017年7月26日 星期三

git branch rebase 操作流程指令

git branch rebase 操作流程指令

如果需要共同作者一起開發的話,一定會用到分支的功能,假設是兩個人的狀態下會需要三個分支。
  • 主分支
  • 作者A
  • 作者B

指令懶人包

新增br1分支
git branch br1
切到br1分支
git checkout br1
如果分支尚未建立可以加入 -b 切換同時創造
git checkout -b br1
合併過程
# 先切到br1分支
git checkout br1

# 分支自己與主線先行合併
git rebase master

# 這時候通常會有衝突,瀏覽一下修正衝突(下面再特別說明)
git add *

# 修復衝突繼續衍合
git rebase --continue

# 復原 rebase 回到 rebase 前的狀態
git rebase --abort
# 切回主線合併 (--no-ff 是 把合併的線分開比較好觀察)
git checkout master
git merge br1 --no-ff

# 復原 merge 回到 mrege 前 (preMaster 是 mrege 前 master 的代碼)
git reset "preMaster" --hard
雖然說是回到,但是merge產生的那個新點是沒有被刪除了只是沒顯示而已,可以使用 git reflog 查先前的點。如果要用快捷可以使用下面兩個
  • merge 使用 git reset HEAD^ —hard
  • rebase 使用 git reset ORIG_HEAD —hard
    要注意的是 ORIG_HEAD 是在操作危險操作時紀錄上一個點,你如果沒有當下馬上用這個ORIG_HEAD 會被蓋過去就不能用了,只能自己查記錄看到底是哪個點 reset 過去。
    HEAD^指的則是相對於目前的上一個點。
合併到主線了,這麼做有個好處是合併的產生的衝突由該分支的作者自己處理,處理完之後也可以決定要不要並回去;而不是直接 merge 把責任交給主作者去看了。
合併完成之後可以刪除不要的分支,要個別刪除本地和遠端的
# 刪除遠端分支
git push origin :fixbug

# 刪除本地分支
git branch -d fixbug
如果是同一條分支你想整理先前的提交可以使用
# 進入互動模式(對你要提交的點 pick 改 f)
git rebase tag -i

# rebase -i 中設置錯了但已經 :wq 離開了,重新設置
git rebase --edit-todo

# 修改提交信息(可選不改就不會保留)
git commit --amend

# 萬事 ok 就繼續吧
git rebase --continue
-i 是互動模式,就像 git add -i 的意思一樣,可以想像成一個方便的工具給你用的感覺。
這個可以讓你修改前面的提交狀況,決定哪些提交點要動哪些不要動,功能有重新提交、合併提交、刪除提交等等很多;
這邊的方式可以想像成另開一個副本對他做修改,所有 rebase 後的節點都是新的節點,最後再加到master之後 (前面的指令切回主線去 mrege)。
另外第一個節點不能動他,要保持是 pick 不然會出現
‘fixup’ without a previous commit
這時候就回去修改 rebase -i 的信息吧~


衝突

不同分支rebase的時候有衝突是正常的,去修復就好了,衝突通常長這個樣子
<<<<<<Head
主線上的內容
=====
分叉上的內容
>>>>>> fixbug上的提交名稱
如果你的分支再分支之後又建立好幾個節點,這邊你就有可能要修幾次衝突,要注意第一次修復的時候可能不是 fixbug 最後那個提交節點的內容。
就是前面提到的不要太多節點,不然這裡要修好幾次;注意看一下應該可以看懂,我一開始不知道會從分岔之後的第一節點開始,一直想說奇怪怎麼會這樣內容怪怪的。
大抵就是把有衝突的地方寫出來給你看,看你是要保留哪一邊,或者都不要另改新的。另改新的這樣做可能不太好,沒有被記錄到;修改的時候記得把 << 、 >> 和 == 這三行刪除。
然後就完成拉,第一次做可能有點慌,會覺得這是三米東西。

適用情況

假設只有單人開發也沒什麼需求,簡單直接在主線上開發(單人而以不太會出問題,不是太重要的專案可以不用保護),然後有一天突然發現壞了,你想要退回前3點重來慢慢加功能回來。
作法就是先回到前3點然後直接開新分支,先把要得主功能手動加回來測試這條分支就直接繼續做但不要分太多點。(做完之後可以考慮對這fixbr1做tag標籤,不然rebase完畢之後這一分支會被隱藏)
做完之後一些不影響到的小功能或註解,目前散落在master結尾3點,你就直接在 fixbr1 做 rebase master 他會要你把 fixbr1 從第一點開始,手動與 master 做合併(有幾點就手動並幾次),這時候散落的無關痛癢小功能再加回來就好,不會漏掉;會影響到的代碼當初再分支上就要先測試好。
rebase 會引上分支上的所有分支節點,然後把這些分支節點加到 master 上,新的分支節點是你在 rebase 的時候手動處理衝突的結果。 master的最後一點也會被隱藏就不見了
如何不做 rebaser 而是直接在主線 merge fixbr1 那路線圖上就有支線,雖然說這樣可能比較清楚,但是如果每次都這樣搞你的路線圖就很慘很醜。


合併提交點

常發生的情況是提交之後才發現,有一個小地方沒改到雖然不是太大重點,但是就是心癢癢的只好又提交一個點,然後這個點就顯得很廢又多餘XD
這邊就就介紹如何合併過往的提交點
假設現在有1~4點,現在第4點 master 你想要把,3合併到2
(你可以 checkout 到 3 也可以不用)
現在進入互動模式
git rebase tag2 -i
這也可以是 tag1 有包含到就好
然後會看到選單把你要合併的點3從 pick 改成 f ,存檔之後即可完成。


參考