2. Main Loop Flow:
2018年12月9日 星期日
[STM32] STM32F072B + FreeRTOS v8.2.3 + VCP + KB + MOUSE + HIDRAW 2 WAY
1. 本篇是基於STM32F072B Discovery Board unboxing + FreeRTOS v8.2.3 + USB_VCP_HID 這一篇為基礎,加上HID RAW雙向的功能後產生的新文章.
2016年1月28日 星期四
How to measure and calibrate Low-speed internal oscillator on STM32F0
1. RTC是經常拿來當作喚醒源的一種應用, 為了節省成本, 通常都是使用內部的RC震盪來當作
起始源, 因此對內部的RC震盪進行校正就很重要了, 底下的範例就是在STM32F0系列上來進
行校正的測試程式.
2. 測試程式主要是參考ST的原始文件Low-speed internal oscillator measurement(AN4067)來寫
的, 當然除了內部的RC校正, 也可以對外部的石英震盪進行校正, 但目前還是先測試最常使
用的內部RC校正.
3. 從文件上的Figure14可以看到校正的原理:
起始源, 因此對內部的RC震盪進行校正就很重要了, 底下的範例就是在STM32F0系列上來進
行校正的測試程式.
2. 測試程式主要是參考ST的原始文件Low-speed internal oscillator measurement(AN4067)來寫
的, 當然除了內部的RC校正, 也可以對外部的石英震盪進行校正, 但目前還是先測試最常使
用的內部RC校正.
3. 從文件上的Figure14可以看到校正的原理:
- 將TIM14設定為input capture mode.
- TIM14_RTC_CLK: TIM14 Channel 1 is connected to RTC input clock. RTC input clock can be LSE, LSI or HSE/div128, 目前設定為LSI.
- 接著利用input capture方式, 計算出LSI的數值.
- 根據User期待喚醒的時間數值參數和LSI計算出最後的wake up counter, 並設定好RTC.
4. 簡易的測試方式:
- 從下圖Logic analyzer的波形上可以看到, 跟我們期待的10msec toggle比起來, 9.992msec已經相當接近10msec了.
5. Test Code Link: 可以參考rtc.c & rtc.h
2016年1月26日 星期二
STM32F0_F3 I2C Master Driver Code
1. STM32F0週邊的架構和F3非常相似, 因此許多的Driver幾乎都是可以共用的, 底下要介紹的是
I2C Master Driver Code.
2. 測試的硬體是使用STM32F072B Discovery Board + MPU6050 Sensor Board, I2C Clock =
400KHz.
3. 首先下載i2c_master.c & i2c_master.h, 並把它加入專案內.
4. 加入後, 接著就可以進行i2c init 和 read/write測試了, 如下面程式碼所示, 使用i2c write 對
mpu6050 初始化, 接著再使用i2c read 讀取 mpu6050 chip id.
5. 可以從MPU6050 Datasheet看到, mpu6050 chip id的位址在0x75, 且chip id固定為0x68, 因此代表 i2c init 及 read chip id皆正常.
6. Logic analyzer 波形圖:
I2C Master Driver Code.
2. 測試的硬體是使用STM32F072B Discovery Board + MPU6050 Sensor Board, I2C Clock =
400KHz.
3. 首先下載i2c_master.c & i2c_master.h, 並把它加入專案內.
4. 加入後, 接著就可以進行i2c init 和 read/write測試了, 如下面程式碼所示, 使用i2c write 對
mpu6050 初始化, 接著再使用i2c read 讀取 mpu6050 chip id.
/* I2C Init */
I2C_Master_Init();
/* I2C Test (mpu6050) */
uint8_t i2c_tmp = 0;
// Reset device.
i2c_tmp = 0x80;
I2C_Write(0xD0, 0x6B, &i2c_tmp, 0x01);
// Delay some time
for(int i=0; i<2000; i++){__asm("nop");}
// Wake up chip.
i2c_tmp = 0x00;
I2C_Write(0xD0, 0x6B, &i2c_tmp, 0x01);
// Read chip id
I2C_Read(0xD0, 0x75, &i2c_tmp, 0x01);
5. 可以從MPU6050 Datasheet看到, mpu6050 chip id的位址在0x75, 且chip id固定為0x68, 因此代表 i2c init 及 read chip id皆正常.
6. Logic analyzer 波形圖:
- I2C Write: (Reset device.)
- I2C Write: (Wake up chip.)
2016年1月18日 星期一
STM32F072B Discovery Board unboxing + FreeRTOS v8.2.3 + USB_VCP_HID
1. 最近在露天買了一張stm32f072b discovery board, 基本上stm32f072 = stm32f051 + usb, 而在研
究了一下之後, 也順手將FreeRTOS v8.2.3和USB Virtual Com-Port & HID移植完畢, 接著會將
移植的過程簡單的描述一下.
究了一下之後, 也順手將FreeRTOS v8.2.3和USB Virtual Com-Port & HID移植完畢, 接著會將
移植的過程簡單的描述一下.
2. main flow:
- 基本上就是先對LED & USB 來做Init.
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq(&RCC_Clocks);
/* Steup Hardware. */
prvSetupHardware();
/* Create task. */
vAltStartTask1Tasks( mainCREATOR_TASK_PRIORITY); //Task1
vAltStartTask2Tasks( mainCREATOR_TASK_PRIORITY); //Task2
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the idle task. */
return 0;
}
static void prvSetupHardware( void )
{
/* LED Init. */
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
STM_EVAL_LEDInit(LED5);
STM_EVAL_LEDInit(LED6);
STM_EVAL_LEDOff(LED3);
STM_EVAL_LEDOff(LED4);
STM_EVAL_LEDOff(LED5);
STM_EVAL_LEDOff(LED6);
/* USB VCP or HID Init. */
USB_Init();
}
- USB VCP & HID的切換在usb_define.h裡面去做選擇.
- Task1: 就是固定每100msec去Toggle LED3而已.
//Task1
static portTASK_FUNCTION( vTask1FunctionTask, pvParameters )
{
portTickType xLastWakeTime;
/* Just to stop compiler warnings. */
( void ) pvParameters;
xLastWakeTime = xTaskGetTickCount();
for( ;; )
{
Task1Task_Counter++;
STM_EVAL_LEDToggle(LED3);
vTaskDelayUntil( &xLastWakeTime, ( 100 / portTICK_RATE_MS ) );
}
}
- Task2: 固定每200msec會去Toggle LED6外, 還會根據usb_define選擇的結果來輸出VCP or HID測試信號.
//Task2
static portTASK_FUNCTION( vTask2FunctionTask, pvParameters )
{
portTickType xLastWakeTime;
/* Just to stop compiler warnings. */
( void ) pvParameters;
xLastWakeTime = xTaskGetTickCount();
for( ;; )
{
Task2Task_Counter++;
STM_EVAL_LEDToggle(LED6);
#ifdef HIDRAW
for(int i=0;i<32;i++)
HID_Buffer[i] = i;
USBD_HID_SendReport (&USB_Device_dev, HID_Buffer, 32);
PrevXferDone = 0;
#endif
#ifdef VirtualComPort
memset(VCP_Buffer,0x00,sizeof(VCP_Buffer));
sprintf(VCP_Buffer, "$,HelloWorld:%d\r\n", vcp_counter++);
USBD_VCP_SendReport(&USB_Device_dev, CDC_IN_EP, (uint8_t*)&VCP_Buffer[0], strlen(VCP_Buffer));
#endif
vTaskDelayUntil( &xLastWakeTime, ( 200 / portTICK_RATE_MS ) );
}
}
3. Test Flow: 當我們利用usb_define.h來切換VCP/HID的時候, 程式會根據切換的結果來做不同
的Init, 因此在裝置管理員上看到的裝置也不相同.
#ifdef HIDRAW #define USBD_VID 0x0483 #define USBD_PID 0x5750 #define USBD_LANGID_STRING 0x409 #define USBD_MANUFACTURER_STRING "STMicroelectronics" #define USBD_PRODUCT_FS_STRING "Custome HID" #define USBD_CONFIGURATION_FS_STRING "HID Config" #define USBD_INTERFACE_FS_STRING "HID Interface" #endif #ifdef VirtualComPort #define USBD_VID 0x0483 #define USBD_PID 0x5740 /** @defgroup USB_String_Descriptors * @{ */ #define USBD_LANGID_STRING 0x409 #define USBD_MANUFACTURER_STRING "STMicroelectronics" #define USBD_PRODUCT_FS_STRING "STM32 Virtual ComPort in FS Mode" #define USBD_CONFIGURATION_FS_STRING "VCP Config" #define USBD_INTERFACE_FS_STRING "VCP Interface" #endif
- HID: 假設我們要測試HID, 可以利用BusHound這套軟體來測試, 它可以針對特定裝置來側錄輸出入的log, 如下圖, 可以看到系統新增出一個HID-compliant device, 透過Hardware ID(VID/PID)可以確認這就是我們目前在使用的stm32f072 discovery board.
- 從log上看到和我們程式的結果符合, 固定每200msec輸出0x00~0x1f這32個bytes.
- VCP:
- 燒錄程式後, 先確認目前ST VCP的編號是多少? (ex: COM14)
- 可以使用Putty來觀察結果, 設定如下.
- 接著就可以看到如下圖的結果:
- Test Video:
4. Test Code Link:
訂閱:
文章 (Atom)
