0. 準備
安裝完成驅動并連接好以后,進入設備管理器可以看到它們都已被識別。
打開putty.exe,選擇串口連接,用于查看之后的串口輸出。
1. 編寫Cube程序,配置UART0為9600,8n1,上電后向串口輸出“Hello”,在PC上通過串口軟件觀察結果;
安裝完成并打開CubeMX軟件,選擇New Project,選擇STM32F103C8Tx并點擊ok。
進入工程界面以后我們可以看到右邊有芯片的引腳圖,如下所示。我們點擊PA11和PA12,選擇GPIO_Input(后面按鈕用)。然后在左邊的配置中將UART1模式定為Half-Duplex。
在生成代碼前,進入工程配置。填寫工程名、保存路徑等,同時選擇IDE為MDK-ARM V5。
設置完成后點擊生成代碼。注意如果沒安裝庫文件的話會提示下載,但通過軟件的自動更新速度無比的慢,而且經常下一半會掛,所以可以在網絡上下載后自助導入。
生成代碼后彈出如下對話框,選擇open。
進入keil5以后可以看到我們的工程文件目錄如左欄所示。注意打開前會彈出Pack installer下載對應的編程工具,選擇stm32f1xx系列即可。下載有點慢,可以自己下載或拷貝他人后導入,路徑為 c:/keil v5/ARM/Pack
然后進入main.c對UART進行配置為9600,8n1,代碼如下所示。
void?UART0_Init(UART_HandleTypeDef*?UartHandle){??
UartHandle->Instance?=?USART1;??
UartHandle->Init.BaudRate?=?9600;??
UartHandle->Init.WordLength?=?UART_WORDLENGTH_8B;??
UartHandle->Init.StopBits?=?UART_STOPBITS_1;??
UartHandle->Init.Parity?=?UART_PARITY_NONE;??
UartHandle->Init.HwFlowCtl?=?UART_HWCONTROL_NONE;??
UartHandle->Init.Mode?=?UART_MODE_TX_RX;??
HAL_UART_Init(UartHandle);??
} ?
在main函數中填上下面兩行代碼-
UART_HandleTypeDef?UartHandle;??
UART0_Init(&UartHandle);??
?
以及輸出hello的代碼
HAL_UART_Transmit(&UartHandle,?(uint8_t*)”hello ”,?7,?500);??
完成代碼后,-準備編譯。選擇flash-設置,進入Utilities標簽,選擇settings,配置如下:
然后F7編譯完成后將程序燒錄至核心板,按一下板子上的reset開關就可以在putty看到串口輸出了。
2. 通過面包板在PA11和PA12各連接一個按鈕開關到地;
3. 編寫Cube程序,配置PA11和PA12為內部上拉到輸入模式,在main()函數循環檢測PA11按鈕按下,并在按鈕按下時 在串口輸出“Pressed”;
可以在CubeMX中圖形化地更改引腳設置,也可以直接在代碼中修改:
void?MX_GPIO_Init(void)??
{??
……??
GPIO_InitStruct.Mode?=?GPIO_MODE_INPUT;??
GPIO_InitStruct.Pull?=?GPIO_PULLUP;??
……??
} ?
在while(1)中添加代碼,循環檢測并輸出
……??
if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11))??
HAL_UART_Transmit(&UartHandle,?(uint8_t*)”Pressed ”,?9,?500);??
else??
HAL_UART_Transmit(&UartHandle,?(uint8_t*)”Not?pressed ”,?13,?500);??
……??
輸出如圖
4. 編寫Cube程序,配置PA12下降沿觸發中斷,程序中設置兩個全局變量,一個為計數器,一個為標識。當中斷觸發 時,計數器加1,并設置標識。
在主循環中判斷標識,如果標識置位則清除標識并通過串口輸出計數值;
在GPIO的init函數中為PIN12設置下降沿中斷,并設置優先級。
GPIO_InitStruct.Pin?=?GPIO_PIN_12;??
GPIO_InitStruct.Mode?=?GPIO_MODE_INPUT;??
GPIO_InitStruct.Pull?=?GPIO_PULLUP;??
GPIO_InitStruct.Mode?=?GPIO_MODE_IT_FALLING;??
HAL_NVIC_SetPriority(EXTI15_10_IRQn,0,0);??
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);??
HAL_GPIO_Init(GPIOA,?&GPIO_InitStruct);??
PA12引腳的下降沿觸發將會觸發中斷,進入函數EXTI15_10_IRQHandler,此時在函數中調用HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12)表示查看PA12的值,如果符合條件,則觸發HAL_GPIO_EXTI_Callback函數。代碼如下
void?HAL_GPIO_EXTI_Callback(uint16_t?GPIO_Pin){??
if?(GPIO_Pin?==?GPIO_PIN_12){??
PA12flag?=?1;??
PA12cnt++;??
}else{??
UNUSED(GPIO_Pin);??
}??
} ?
在main函數的while循環中添加代碼:
if(PA12flag?==?1){??
PA12flag?=?0;??
size?=?sprint(str,?”Count:?%d ”,PA12cnt);??
HAL_UART_Transmit(&UartHandle,?(uint8_t*)str,?size,?500);??
} ?
5. 編寫Cube程序,開啟定時器為200ms中斷一次,中斷觸發時設置標識,主循環根據這個標識來做串口輸出(取消4 的串口輸出);
使用TIM3定時器,如果不是CUBEMX生成代碼的話記得添加頭文件引用。
添加init函數:
void?TIM_Init(){??
TIM_Handle.Instance?=?TIM3;??
TIM_Handle.Init.Prescaler?=?8000;??
TIM_Handle.Init.CounterMode?=?TIM_COUNTERMODE_UP;??
TIM_Handle.Init.Period?=?199;??
TIM_Handle.Init.ClockDivision?=?TIM_CLOCKDIVISION_DIV1;??
HAL_TIM_Base_Init(&TIM_Handle);??
sClockSourceConfig.ClockSource?=?TIM_CLOCKSOURCE_INTERNAL;?//設置時鐘源為內部時鐘??
HAL_TIM_ConfigClockSource(&TIM_Handle,?&sClockSourceConfig);??
sMasterConfig.MasterOutputTrigger?=?TIM_TRGO_RESET;//設置復位模式,發生觸發輸入事件時計數器和預分頻器能重新初始化??
sMasterConfig.MasterSlaveMode?=?TIM_MASTERSLAVEMODE_DISABLE;??
HAL_TIMEx_MasterConfigSynchronization(&TIM_Handle,?&sMasterConfig);??
HAL_NVIC_SetPriority(TIM3_IRQn,?0,?0);//設置優先級??
HAL_NVIC_EnableIRQ(TIM3_IRQn);enable中斷向量表處理????
}??
和之前設置的中斷一樣需要覆寫中斷觸發函數TIM3_IRQHandler,而后在其中對時鐘進行判斷后觸發HAL_TIM_PeriodElapsedCallback。并在callback中實現操作。
TIM_HandleTypeDef?TIM_Handle;??
TIM_ClockConfigTypeDef?sClockSourceConfig;??
TIM_MasterConfigTypeDef?sMasterConfig;?????
int?TIMflag?=?0,?PA12flag?=?0;??
int?TIMcnt?=?0,?PA12cnt?=?0,?totalcnt?=?0;??
void?TIM3_IRQHandler(void){??
HAL_TIM_IRQHandler(&TIM_Handle);??
}??
void?HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef?*htim){?????
TIMflag?=?1;??
TIMcnt++;??
} ?
6. 編寫完整的碼表程序,PA12的按鈕表示車輪轉了一圈,通過計數器可以得到里程,通過定時器中斷得到的時間可以計算出速度;PA11的按鈕切換模式,模式一在串口輸出里程,模式二在串口輸出速度。
在main函數中實現碼表程序:
while?(1)??
{??
/*?USER?CODE?END?WHILE?*/??
/*?USER?CODE?BEGIN?3?*/??
if(TIMflag?==?1){??
TIMflag?=?0;??
if(TIMcnt?==?5){每五個周期輸出一次??
speed?=?2?*?PA12cnt?/?1;//五個周期為1秒,車輪周長2米??
6. 編寫完整的碼表程序,PA12的按鈕表示車輪轉了一圈,通過計數器可以得到里程,通過定時器中斷得到的時間可以計算出速度;PA11的按鈕切換模式,模式一在串口輸出里程,模式二在串口輸出速度。
在main函數中實現碼表程序:
[cpp] view plain copywhile (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(TIMflag == 1){
TIMflag = 0;
if(TIMcnt == 5){每五個周期輸出一次
speed = 2 * PA12cnt / 1;//五個周期為1秒,車輪周長2米
TIMcnt = 0;
if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11))
mode = 1 - mode;//PA11按鈕負責模式切換
switch(mode){
case 0:
size = sprintf(str, “Speed : %f ”,speed);//輸出速度
HAL_UART_Transmit(&UartHandle, (uint8_t*)str, size, 500);
break;
case 1:
size = sprintf(str, “Mileage: %d ”, 2 * totalcnt);//輸出里程
HAL_UART_Transmit(&UartHandle, (uint8_t*)str, size, 500);
break;
default:break;
}
PA12cnt = 0;
} }
評論
查看更多