NUCLEO-F412ZG板子上的元器件並沒有完全焊接,除去ST-LINK部分和電源部分后,還有用一個USB主機接口,三個LED燈和兩個按鈕,不過很多功能引腳都已經引到了插針。查看原理圖可發現,由原理圖模塊的5大部分與電源部分組成,即連接端子、ST-LINK、MCU、USB、以太網和電源部分。
電源部分考慮的非常充分,5V有三路輸入,一路是有外部輸入6-15VDC電源經U5(LD1117S50TR)轉為5VDC電源;第二路是USB端口提供的5V電源,同時還有電流限制保護U4(ST890CDR);第三路則是由外部直接輸入5V電源。默認是選擇的USB口電源輸入,並U6(LD39050PU33R)輸出3.3VDC電源。當然還有ST-LINK部分的電源以及USB主機部分的電源。而且這兩部分也是上述3路5VDC供電。
以太網部分的電路並未焊接。時鍾部分ST-LINK使用了8M的外部晶振(X1),而F412的主時鍾輸入有兩路,一路是從ST-LINK的主控芯片MCO引來,一路也是外界的8M外部晶振(X3)。板子采用的是從MCO引來的時鍾。此外還有一個32.768K的外部晶振(X2)。
在了解了基本電路后,開始編程之旅,使用的開發環境是IAR EWARM7.5。首先使用STM32CubeMX創建一個項目。打開STM32CubeMX出現如下的界面。
點擊“New Project”新建一個項目,彈出新項目對話框:
由於使用的是NUCLEO-F412ZG開發板,所以選擇Board Selector標簽,並選擇板子的類型為Nucleo144,選擇MCU系列為STM32F4,點擊“OK”按鈕創建項目,出現如下界面:
在第一個項目中我們簡單的利用開發板上提供的按鈕B1來控制開發板上的三個指示燈LD1(綠色)、LD2(藍色)、LD3(紅色)其中:
按鈕B1對應的輸入引腳為:PC13
綠色指示燈LD1對應的引腳為:PB0
藍色指示燈LD2對應的引腳為:PB7
紅色指示燈LD3對應的引腳為:PB14
同時通過引腳PG2來驅動外圍的繼電器電路,這部分電路由自己搭建。原理圖如下:
對於IO的配置可以在STM32CubeMX中完成,將PC13配置為GPIO_EXIT13;將PB0、PB7、PB14與PG2都配置為GPIO_OUTPUT。配置好GPIO引腳的類型后就可以在”Configuration“標簽(如下圖所示)中配置GPIO口了。
在“System“下,選擇GPIO彈出”Pin Configuration“對話框。在對話框中一一配置各個GPIO引腳,在本次中我配置個引腳如下:
完成以上配置后,生成IAR EWARM項目則會在生成的源碼中出現GPIO的配置,源碼如下:
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : LD1_Pin LD3_Pin LD2_Pin */
GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : STLK_RX_Pin STLK_TX_Pin */
GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : Relay_Ctrl_Pin USB_PowerSwitchOn_Pin */
GPIO_InitStruct.Pin = Relay_Ctrl_Pin|USB_PowerSwitchOn_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pin : USB_OverCurrent_Pin */
GPIO_InitStruct.Pin = USB_OverCurrent_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : USB_SOF_Pin USB_ID_Pin USB_DM_Pin USB_DP_Pin */
GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOG, Relay_Ctrl_Pin|USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);
在硬件配置方面,STM32CubeMX能夠完成全部的基礎工作,我們只需要完成自己的控制邏輯,非常方便。如果設計的好,我們自己學的程序的通用性可以大大提高,極大降低與底層硬件的耦合強度。不過在使用中發現STM32CubeMX似乎與中文操作系統配合得不太好,總是出現全角字符的困擾,估計ST不久會解決。
我的測試邏輯比較簡單,一開始三個指示燈全部亮,繼電器不導通。按鈕B1按一下,LD1滅,再按一下LD2滅,再按一下LD3滅同時繼電器吸合,再按一下三個燈全亮同時繼電器斷開,如此循環。
這部分的源碼實現也比較簡單,首先定義了一個表示狀態的枚舉類型,然后根據不通的狀態定義邏輯操作。
typedef enum
{
STATE0 = 0,
STATE1,
STATE2,
STATE3,
STATENUM
}STATE;
/*邏輯控制的實現*/
void LogicCtrol(void)
{
GPIO_PinState b1State=HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin);
if(b1State==GPIO_PIN_SET)
{
status++;
}
if(status>=STATENUM)
{
status=STATE0;
}
switch(status)
{
case STATE0:
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOG, Relay_Ctrl_Pin, GPIO_PIN_RESET);
break;
}
case STATE1:
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, LD3_Pin|LD2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOG, Relay_Ctrl_Pin, GPIO_PIN_RESET);
break;
}
case STATE2:
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, LD3_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOG, Relay_Ctrl_Pin, GPIO_PIN_RESET);
break;
}
case STATE3:
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD2_Pin|LD3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOG, Relay_Ctrl_Pin, GPIO_PIN_SET);
break;
}
default:
{
break;
}
}
}
下載到NUCLEO-F412ZG開發板測試,結果與預期一致。