顯示具有 stm32f4 標籤的文章。 顯示所有文章
顯示具有 stm32f4 標籤的文章。 顯示所有文章

2018年3月7日 星期三

STM32F4 如何輕鬆的自訂 LED 任意腳位初始化 與 點亮

STM32F4 如何輕鬆的自訂 LED 任意腳位初始化 與 點亮

有鑑於官方預設語言是C,想要點亮LED要做的工作也是有點多行,寫個一兩個還不是什麼大事,寫個幾10個然後發現有錯要修改,就難過了。
前一陣子在PTT看到有人用 macro 在 C 上面弄出 STL ,仿物件實在很牛QuQ
雖然看不董細節怎麼做的,不過至少原理是解了的,依樣畫葫蘆刻了一個做練習
/**
  * @brief  LED initial Obj
  * @author None
  * @site   https://charlottehong.blogspot.tw/
  */
#define STATEMENT_(...)  do {__VA_ARGS__} while (0)
#define LED                                               \
struct HAL_LED{                                           \
  GPIO_TypeDef* port;                                     \
  uint16_t pin;                                           \
  GPIO_InitTypeDef  GPIO_InitStruct;                      \
}
#define GPIO_ENABLE(GPIO)                                 \
STATEMENT_(                                               \
  __HAL_RCC_##GPIO##_CLK_ENABLE();                        \
)
#define LED_init(self, GPIO, GPIO_PIN, state)             \
STATEMENT_(                                               \
  self.port=(GPIO);                                       \
  self.pin=(GPIO_PIN);                                    \
  __HAL_RCC_##GPIO##_CLK_ENABLE();                        \
                                                          \
  self.GPIO_InitStruct.Pin = self.pin;                    \
  self.GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;        \
  self.GPIO_InitStruct.Pull = GPIO_PULLUP;                \
  self.GPIO_InitStruct.Speed = GPIO_SPEED_FAST;           \
                                                          \
  HAL_GPIO_Init(self.port, &self.GPIO_InitStruct);        \
  HAL_GPIO_WritePin(self.port, self.pin, state);          \
)
#define LED_WritePin(self, state)                         \
STATEMENT_(                                               \
  HAL_GPIO_WritePin(self.port, self.pin, state);          \
)
#define LED_TogglePin(self)                               \
STATEMENT_(                                               \
  HAL_GPIO_TogglePin(self.port, self.pin);                \
)

使用範例

你可以在主程式新增一個仿物件
LED led1;
然後對著他初始化,就是設定角位(下面是設置成 PC4)
LED_init(led1, GPIOG, GPIO_PIN_2, GPIO_PIN_RESET );
GPIO_PIN_RESET 起始狀態是0
GPIO_PIN_SET 起始狀態是1
然後我們點亮他吧
LED_TogglePin(led1);
嗯就這麼簡單,要加函式在自己加~應該很容易能看懂

2017年8月24日 星期四

STM32F469I GPIO 基本的按鈕與LED控制 彙總整理

STM32F469I GPIO 基本的按鈕與LED控制 彙總整理

前面兩篇介紹
  1. STM32F469I GPIO 基本的閃爍控制
  2. STM32F469I GPIO 基本的按鈕控制
這篇彙整一下順變仿照官方的函式打造了D0~D15的使用模式
整串貼進去官方GPIO範例程序內的 main 之上即可。

使用方式範例

D15 沒有接地時 D2 D3 亮起
下面貼在 main 內
  BSP_LED_Init(LED1);
  BSP_LED_Init(LED2);
  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);
  // 初始化 ArD 腳位為 OUT
  Ard_LED_Init(ArD2);
  Ard_LED_Init(ArD3);
  // 初始化 ArD 腳位為 IN
  Ard_PB_Init(ArD15);

  while(1)
  {
    /* 按鈕 */
    if(Ard_PB_GetState(ArD15) == PB_RESET)
    {
      /* 按住 */
      Ard_LED_On(ArD2);
      Ard_LED_On(ArD3);
    }
    else if(Ard_PB_GetState(ArD15) == PB_SET)
    {
      /* 放開 */
      Ard_LED_Off(ArD2);
      Ard_LED_Off(ArD3); 
    }
  }

STM32F469I GPIO 基本的按鈕控制

STM32F469I GPIO 基本的按鈕控制

腳位的部分或LED控制可以參考上一篇
https://charlottehong.blogspot.tw/2017/07/stm32f469i-gpio.html

按鈕初始化

/* UserDefine functions ------------------------------------------------------*/
void User_LED_Init()
{
  // 設定角位(3行都要改)
  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_RESET);
}
與前一章節一樣需要設置 Set port and pin 內的參數三行,這裡設置的事 PB8 也就是 Arduino腳位的 D15 的腳位置。

偵測按鈕

這個直接在放主程式main的 while 回圈內就可以
D15放空或接5V會讓D2 D3亮,D15接地則滅。
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == PB_RESET)
{
  /* 接地 */
  HAL_GPIO_WritePin(ArD2_GPIO_PORT, ArD2_PIN, GPIO_PIN_SET);
  HAL_GPIO_WritePin(ArD3_GPIO_PORT, ArD3_PIN, GPIO_PIN_SET);
}
else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == PB_SET)
{
  /* 放開 */
  HAL_GPIO_WritePin(ArD2_GPIO_PORT, ArD2_PIN, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(ArD3_GPIO_PORT, ArD3_PIN, GPIO_PIN_RESET);  
}

2017年8月10日 星期四

stm32f469i GUI 如何放入自訂圖片 如何轉換圖檔給stm讀取

stm32f469i GUI 如何放入自訂圖片 如何轉換圖檔給stm讀取

打開這一份範例:
STM32Cube_FW_F4_V1.16.0\Projects\STM32469I-Discovery\Examples\LCD_DSI\LCD_DSI_CmdMode_DoubleBuffering
預設有兩張圖片,這兩張個別是
  • image_320x240_argb8888
  • life_augmented_argb8888
放置的位置在
LCD_DSI_CmdMode_DoubleBuffering\Inc
他是一份 .h 檔案定義了這張圖片,裡面長這個樣子
const uint32_t life_augmented_argb8888[76800] =
{
0xFFFFFFFF,
0xFFFFFFFF,
...
};
這裡就是圖片的像素質了,兩個兩個一組看,第一組FF是透明度,越大越不透明,再來個別是 R, G, B 依序比如說一個顏色的 RGB 是 50, 100, 150 對應到的格式就是 0xFF326496。
我寫了一個轉換程序,可以把 BMP 圖檔轉換到 .h 檔,需要的可以參考。
Bmp_to_ARGB888
使用方式直接拉BMP圖檔到解壓縮出來的 exe 上然後放開即可(可以一次拉好幾個進去)。
圖檔只能放exe旁邊(寫的時候沒注意到的小Bug)
或者使用CMD指令(一樣要放一起)
Bmp_to_ARGB888.exe p1.bmp p2.bmp

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年7月31日 星期一

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月4日 星期二

從零開始使用 STM32 F469I 燒錄測試程式

從零開始使用 STM32 F469I 燒錄測試程式

大多數的時候我發現其實真正不能起手的是不知道怎麼燒錄!不知道為什麼網路上大多都只教學如何改代碼代碼是什麼意思,如果今天給你一塊板子你該怎麼辦?
這篇文章主要就是介紹如何從零開始,你手上只有板子你什麼都沒有怎麼辦?

預裝軟體

  1. MDK523.EXE (Keil uVision5)
    可以從官方下載免費版的,可以用只是會限制上傳大小
  2. ST-Link
    可以從板子上的網址連過去下載
  3. Keil.STM32F4xx_DFP.2.9.0
    可以直接從uVision5內更新或下載
  4. 範例代碼
    可以從板子上的網址連過去下載

uVision5

到官方下載,可以直接用,免費版本有限制。
官方網址:http://www2.keil.com/mdk5/
幫你點好了懶人包:http://www2.keil.com/mdk5/install

板子上會有一個網址,連過去可以下載,大概會長這個樣子

幫你打上來大概F4系列都是同一個
網址:http://www.st.com/stm32f4-discovery

接下來找到你自己的型號,以這邊範例是這個

拉到最下面這裡只是版本差異都可以

下載,不過會要你填一些資訊,之後會把載點寄到信箱,記得不要亂填

載好之後直接安裝,看你電腦幾位元的就安裝什麼

Keil.STM32F4xx_DFP

這個是keil裡面的套件,可以直接線上更新,記得要連網不然會看不到。
需要什麼就選什麼裝就好,還蠻大的要花不少時間慢跑
到這邊環境已經架設好可以跑瞜~
手動下載離線包可以到下面連結找到相對應的板子型號,一樣在上方的畫面左上角 File 點進去之後按加入,可以不用解開壓縮檔直接按加入。
http://www.keil.com/dd2/pack/

範例代碼

在剛剛 ST-Link 下載的網址
這裡整個F4系列的都共用的,都包含進去了
解壓縮之後開啟這個位置
STM32Cube_FW_F4_V1.16.0\Projects\STM32469I-Discovery\Examples
粗體型號必須選自己的板子,這個型號盒子上有寫,有些型號版本有細微的差異,板子本身沒有打印。
這裡進來就是各項使用的範例,我們使用最簡單的GPIO當測試,可以從板子上內建的按鈕與LED燈測試燒錄成功。
進來之後選擇 GPIO\GPIO_EXTI\MDK-ARM MDK-ARM是寫給我們剛剛安裝的軟體用的範例代碼。

執行

開啟剛剛的GPIO測試
接下來先按編譯,這裡第一次要按全部編譯,會比較久,第二次如過只動一份檔案可以按他左邊的只重新編譯當前文件,這樣比較省時間。
編譯完畢之後執行,執行要手動跑一下程序左邊四個自己選,跑完結束的地方像圖中那樣,接下來按一下板子藍色的按鈕,翻到正面看LED會跟著你按的時候做出變化。
如果想直接讓他跑到底直接看結束,可以翻板子後面reset按一下就會自動跑完了,不過跑完就不能重來了,要除錯再按 ctrl+f5 重跑一次就好了。

參考