日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

基于STM32的uc/OS系统移植及用Saleae Logic 16抓取分析波形

發(fā)布時間:2024/3/26 windows 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于STM32的uc/OS系统移植及用Saleae Logic 16抓取分析波形 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 一、關(guān)于uc/OS系統(tǒng)
      • 1.操作系統(tǒng)與裸機的區(qū)別
      • 2.uc/OS運行流程
    • 二、詳細移植過程
      • 1.STM32Cubex創(chuàng)建工程
      • 2.為工程添加源碼
      • 3.添加頭文件路徑
      • 4.添加代碼
        • 1)bsp.h和bsp.c
        • 2)main.c
        • 3)usart.c
        • 4)修改其他代碼
      • 5.其他設(shè)置
      • 6.實際效果
    • 三、分析引腳波形
      • 1.Keil虛擬仿真邏輯儀
      • 2.真實邏輯儀(SaleaeLogic16)
    • 四、總結(jié)
    • 五、參考資料

一、關(guān)于uc/OS系統(tǒng)

1.操作系統(tǒng)與裸機的區(qū)別

裸機運行的程序代碼,一般由一個main函數(shù)中的while死循環(huán)和各種中斷服務(wù)程序組成,平
時CPU執(zhí)行while循環(huán)中的代碼,出現(xiàn)其他事件時,跳轉(zhuǎn)到中斷服務(wù)程序進行處理,沒有多任
務(wù)、線程的概念。而引人操作系統(tǒng)后,程序運行時可以把一個應(yīng)用流程分割為多個任務(wù),每個任務(wù)完成一部分工作,并且每個任務(wù)都可以寫成死循環(huán)。操作系統(tǒng)根據(jù)任務(wù)的優(yōu)先級,通過調(diào)度器使CPU分時執(zhí)行各個任務(wù),保證每個任務(wù)都能夠得到運行。若調(diào)度方法優(yōu)良,則可使各任務(wù)看起來是并行執(zhí)行的,減少了CPU的空閑時間,提高了CPU的利用率。

2.uc/OS運行流程

在運行uC/OS系統(tǒng)的設(shè)備上,當(dāng)程序執(zhí)行時,首先會初始化系統(tǒng)任務(wù)管理所需要的各種鏈表等數(shù)據(jù)結(jié)構(gòu),接著根據(jù)應(yīng)用程序需求創(chuàng)建任務(wù),最后由調(diào)度器管理各個任務(wù),而中斷可由操作系統(tǒng)使能和除能,若使能中斷則可以在其他任務(wù)運行時跳轉(zhuǎn)到中斷服務(wù)程序。

uc/OS工作流程圖

1)初始化所有全局變量、數(shù)據(jù)結(jié)構(gòu),創(chuàng)建最低優(yōu)先級空閑任務(wù)OSTaskIde (如果使用了統(tǒng)計任務(wù),也在此創(chuàng)建),創(chuàng)建6個空數(shù)據(jù)鏈表:

  • 空任務(wù)控制塊鏈表
  • 空事件控制塊鏈表
  • 空隊列控制塊鏈表
  • 空標(biāo)志組鏈表
  • 空內(nèi)存控制塊鏈表
  • 空閑定時器控制塊鏈表
    2)至少創(chuàng)建一個任務(wù)。一般創(chuàng)建一個最高優(yōu)先級別
    TaskStart任務(wù)(建議), 任務(wù)調(diào)度后,在這個任務(wù)中再創(chuàng)建其他任務(wù),初始化硬件并開中斷。
    3)進入多任務(wù)管理階段,將就緒表中最高優(yōu)先級任務(wù)的
    棧指針加載到SP中,并強制中斷返回。
    4) μC/OS 的任務(wù)調(diào)度工作。任務(wù)調(diào)度是內(nèi)核的主要服務(wù),是區(qū)分裸機和多任務(wù)系統(tǒng)的最大特點,好的調(diào)度策略能更好地發(fā)揮系統(tǒng)的效率。調(diào)度工作主要包括:查找就緒表中最高優(yōu)先級任務(wù)和實現(xiàn)任務(wù)切換。而任務(wù)切換又分為兩種,分別為任務(wù)級的調(diào)度器OSSched和中斷級的調(diào)度器OSIntExt。
    5)運行用戶任務(wù),某些用戶任務(wù)會因為主動讓出CPU、延時、請求臨界資源或優(yōu)先級不夠高而掛起,由調(diào)度器調(diào)度運行其他任務(wù)。
    6) μC/OS的任務(wù)調(diào)度是靠周期時鐘中斷來實現(xiàn)的,每個時鐘節(jié)拍到來就會產(chǎn)生一次定時中斷,中斷后啟動調(diào)度器,運行就緒表中優(yōu)先級最高的任務(wù)(非搶占型內(nèi)核中斷后繼續(xù)運行被中斷任務(wù))。即過一段時間就檢測是否有重要任務(wù)需要運行,若是就轉(zhuǎn)而運行更重要的任務(wù),從而確保實時性(裸機程序就無法這樣做了)。在CM3芯片平臺上,這個周期時鐘中斷由SysTick提供。

二、詳細移植過程

將uc/OS-III移植到stm32上,構(gòu)建3個任務(wù):其中兩個task分別以1s和3s周期對LED等進行點亮-熄滅的控制;另外一個task以2s周期通過串口發(fā)送“hello uc/OS! 歡迎來到RTOS多任務(wù)環(huán)境!”。

1.STM32Cubex創(chuàng)建工程

新建project,選擇要用的芯片,這里選擇STM32F103C8,選中星號開啟項目。

配置調(diào)試接口為Serial Wire。

配置時鐘源,選擇Crystal/Ceramic Resonator。

將PC13、PA3設(shè)置為GPIO_OUTPUT模式,控制LED燈的亮滅,作為判斷是否移值成功的依據(jù)。

設(shè)置串口USART1為異步模式Asynchronous。
設(shè)置工程相關(guān)信息,并點擊GENERATE CODE。

2.為工程添加源碼

在工程相同目錄下新建下圖所示文件夾,提前把下的源碼整理進去,后面操作起來就會方便很多。

用Keil打開生成的工程,為項目添加如下圖所示文件夾。

點擊ADD FILES,選擇ALL FILES,將提前整理好的源碼添加進項目中的CPU文件夾。


點擊LIB,將下圖所示文件添加進項目中。


點擊PORT,將下圖所示文件夾加入項目中。
點擊Source,將下圖所示文件加入項目中。

點擊 CONFIG,將下圖所示文件添加進項目中。

點擊BSP,將下圖所示文件添加進項目中。

3.添加頭文件路徑

點擊魔法棒,選擇C/C++,點進Include Paths。

將下圖所示的頭文件路徑添加進項目中。

4.添加代碼

1)bsp.h和bsp.c

bsp.h

// bsp.h #ifndef __BSP_H__ #define __BSP_H__ #include "stm32f1xx_hal.h" void BSP_Init(void); #endif

bsp.c

// bsp.c #include "includes.h" #define DWT_CR *(CPU_REG32 *)0xE0001000 #define DWT_CYCCNT *(CPU_REG32 *)0xE0001004 #define DEM_CR *(CPU_REG32 *)0xE000EDFC #define DBGMCU_CR *(CPU_REG32 *)0xE0042004 #define DEM_CR_TRCENA (1 << 24) #define DWT_CR_CYCCNTENA (1 << 0) CPU_INT32U BSP_CPU_ClkFreq (void) { return HAL_RCC_GetHCLKFreq(); } void BSP_Tick_Init(void) {CPU_INT32U cpu_clk_freq;CPU_INT32U cnts;cpu_clk_freq = BSP_CPU_ClkFreq();#if(OS_VERSION>=3000u)cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;#elsecnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;#endifOS_CPU_SysTickInit(cnts); } void BSP_Init(void) {BSP_Tick_Init();MX_GPIO_Init(); } #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) void CPU_TS_TmrInit (void) {CPU_INT32U cpu_clk_freq_hz;DEM_CR |= (CPU_INT32U)DEM_CR_TRCENA; DWT_CYCCNT = (CPU_INT32U)0u;DWT_CR |= (CPU_INT32U)DWT_CR_CYCCNTENA;cpu_clk_freq_hz = BSP_CPU_ClkFreq();CPU_TS_TmrFreqSet(cpu_clk_freq_hz); } #endif #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) CPU_TS_TMR CPU_TS_TmrRd (void) {return ((CPU_TS_TMR)DWT_CYCCNT); } #endif #if (CPU_CFG_TS_32_EN == DEF_ENABLED) CPU_INT64U CPU_TS32_to_uSec (CPU_TS32 ts_cnts) {CPU_INT64U ts_us;CPU_INT64U fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);return (ts_us); } #endif #if (CPU_CFG_TS_64_EN == DEF_ENABLED) CPU_INT64U CPU_TS64_to_uSec (CPU_TS64 ts_cnts) {CPU_INT64U ts_us;CPU_INT64U fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC); return (ts_us); } #endif

2)main.c

/* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* 任務(wù)優(yōu)先級 */ #define START_TASK_PRIO 3 #define LED0_TASK_PRIO 4 #define MSG_TASK_PRIO 5 #define LED1_TASK_PRIO 6/* 任務(wù)堆棧大小 */ #define START_STK_SIZE 96 #define LED0_STK_SIZE 64 #define MSG_STK_SIZE 64 #define LED1_STK_SIZE 64/* 任務(wù)棧 */ CPU_STK START_TASK_STK[START_STK_SIZE]; CPU_STK LED0_TASK_STK[LED0_STK_SIZE]; CPU_STK MSG_TASK_STK[MSG_STK_SIZE]; CPU_STK LED1_TASK_STK[LED1_STK_SIZE];/* 任務(wù)控制塊 */ OS_TCB StartTaskTCB; OS_TCB Led0TaskTCB; OS_TCB MsgTaskTCB; OS_TCB Led1TaskTCB;/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* 任務(wù)函數(shù)定義 */ void start_task(void *p_arg); static void AppTaskCreate(void); static void AppObjCreate(void); static void led_pc13(void *p_arg); static void send_msg(void *p_arg); static void led_pa3(void *p_arg); /* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /*** @brief System Clock Configuration* @retval None*/ void SystemClock_Config(void) {RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/**Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/**Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();} }/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/ int main(void) {OS_ERR err;OSInit(&err);HAL_Init();SystemClock_Config();//MX_GPIO_Init(); 這個在BSP的初始化里也會初始化MX_USART1_UART_Init(); /* 創(chuàng)建任務(wù) */OSTaskCreate((OS_TCB *)&StartTaskTCB, /* Create the start task */(CPU_CHAR *)"start task",(OS_TASK_PTR ) start_task,(void *) 0,(OS_PRIO ) START_TASK_PRIO,(CPU_STK *)&START_TASK_STK[0],(CPU_STK_SIZE) START_STK_SIZE/10,(CPU_STK_SIZE) START_STK_SIZE,(OS_MSG_QTY ) 0,(OS_TICK ) 0,(void *) 0,(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR *)&err);/* 啟動多任務(wù)系統(tǒng),控制權(quán)交給uC/OS-III */OSStart(&err); /* Start multitasking (i.e. give control to uC/OS-III). */}void start_task(void *p_arg) {OS_ERR err;CPU_SR_ALLOC();p_arg = p_arg;/* YangJie add 2021.05.20*/BSP_Init(); /* Initialize BSP functions *///CPU_Init();//Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); //統(tǒng)計任務(wù) #endif#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了測量中斷關(guān)閉時間CPU_IntDisMeasMaxCurReset(); #endif#if OS_CFG_SCHED_ROUND_ROBIN_EN //當(dāng)使用時間片輪轉(zhuǎn)的時候//使能時間片輪轉(zhuǎn)調(diào)度功能,時間片長度為1個系統(tǒng)時鐘節(jié)拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //進入臨界區(qū)/* 創(chuàng)建LED0任務(wù) */OSTaskCreate((OS_TCB * )&Led0TaskTCB, (CPU_CHAR * )"led_pc13", (OS_TASK_PTR )led_pc13, (void * )0, (OS_PRIO )LED0_TASK_PRIO, (CPU_STK * )&LED0_TASK_STK[0], (CPU_STK_SIZE)LED0_STK_SIZE/10, (CPU_STK_SIZE)LED0_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR * )&err); /* 創(chuàng)建LED1任務(wù) */OSTaskCreate((OS_TCB * )&Led1TaskTCB, (CPU_CHAR * )"led_pa3", (OS_TASK_PTR )led_pa3, (void * )0, (OS_PRIO )LED1_TASK_PRIO, (CPU_STK * )&LED1_TASK_STK[0], (CPU_STK_SIZE)LED1_STK_SIZE/10, (CPU_STK_SIZE)LED1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR * )&err); /* 創(chuàng)建MSG任務(wù) */OSTaskCreate((OS_TCB * )&MsgTaskTCB, (CPU_CHAR * )"send_msg", (OS_TASK_PTR )send_msg, (void * )0, (OS_PRIO )MSG_TASK_PRIO, (CPU_STK * )&MSG_TASK_STK[0], (CPU_STK_SIZE)MSG_STK_SIZE/10, (CPU_STK_SIZE)MSG_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err);OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //掛起開始任務(wù) OS_CRITICAL_EXIT(); //進入臨界區(qū) } /*** 函數(shù)功能: 啟動任務(wù)函數(shù)體。* 輸入?yún)?shù): p_arg 是在創(chuàng)建該任務(wù)時傳遞的形參* 返 回 值: 無* 說 明:無*/ static void led_pc13 (void *p_arg) {OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */ #endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */ }static void led_pa3 (void *p_arg) {OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */ #endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */ }static void send_msg (void *p_arg) {OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */ #endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){printf("hello uc/OS \r\n");OSTimeDlyHMSM(0, 0, 2, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */ }/* USER CODE BEGIN 4 */ /*** 函數(shù)功能: 創(chuàng)建應(yīng)用任務(wù)* 輸入?yún)?shù): p_arg 是在創(chuàng)建該任務(wù)時傳遞的形參* 返 回 值: 無* 說 明:無*/ static void AppTaskCreate (void) {}/*** 函數(shù)功能: uCOSIII內(nèi)核對象創(chuàng)建* 輸入?yún)?shù): 無* 返 回 值: 無* 說 明:無*/ static void AppObjCreate (void) {}/* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/ void Error_Handler(void) {/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */ }#ifdef USE_FULL_ASSERT /*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

3)usart.c

添加以下代碼對printf函數(shù)進行重定向。

int fputc(int ch,FILE *f){HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);return ch; }

4)修改其他代碼

找到Application/MDK-ARM下的startup_stm32f103xb.s文件,將PendSV_Handler和SysTick_Handler改為OS_CPU_PendSVHandler和OS_CPU_SysTickHandler。


找到CONFIG下的app_cfg.h文件,將DEF_ENABLED改為DIABLED。

將#define APP_TRACE BSP_Ser_Printf 改為#define APP _TRACE (void)。

在該目錄下找到文件includes.h,添加包含兩個頭文件gpio.h、app_cfg.h。

將#include < stm32f10x lib.h> 改為#include "stm32f1xx hal.h"

在該目錄下找到lib_cfg.h,修改堆空間的大小,改成5k,因為STM32F103C8RAM太小了,不修改編譯會報錯。

5.其他設(shè)置

如下圖所示修改設(shè)置,這個為Initialization File添加在同一目錄下debug.ini文件的路徑,這里為待會使用邏輯分析儀抓取引腳波形做準(zhǔn)備,如果不添加待會仿真時按下全速運行會自動停止并報錯沒有讀取權(quán)限。

debug.ini

map 0x40000000, 0x40007FFF read write // APB1 map 0x40010000, 0x400157FF read write // APB2 map 0x40020000, 0x4007FFFF read write // AHB1 map 0x50000000, 0x50060BFF read write // AHB2 map 0x60000000, 0x60000FFF read write // AHB3 map 0xE0000000, 0xE00FFFFF read write // CORTEX-M4 internal peripherals


IRAM也設(shè)置的大一些。

6.實際效果

將生成的hex文件燒錄進芯片中,然后將boot0置0,看到實際效果如下:兩個LED按不同的周期點亮、熄滅,串口調(diào)試助手上輸出“hello uc/OS! 歡迎來到RTOS多任務(wù)環(huán)境!”。

三、分析引腳波形

分別使用Keil虛擬仿真邏輯儀和真實邏輯儀(SaleaeLogic16)抓取LED輸出電平和串口通信的波形,進行協(xié)議分析。

1.Keil虛擬仿真邏輯儀

進入Keil,按Ctrl+F5進入仿真調(diào)試,打開邏輯分析儀。

點擊左上角的SET UP,添加要觀察的引腳PA3、PC13和串口,輸入時輸入PORTA.3,然后回車就會自動生成下圖所示的表示形式,注意Display Type要設(shè)置成Bit形式。

按F5全速運行,可以看到下圖所示的波形:

一個網(wǎng)格是0.5S,兩只LED燈一只以1S的周期,一只以3秒的周期在高低電平轉(zhuǎn)換,串口發(fā)送數(shù)據(jù)的周期是2S,在邏輯分析儀上不好詳細分析串口的波形,但在SaleaeLogic16的軟件上就能比較直觀地分析。

2.真實邏輯儀(SaleaeLogic16)

想要詳細了解SaleaeLogic16可以看我這篇博客用 Saleae Logic 16 示波器測量并分析 I2C、SPI、串口的信號
這里使用SaleaeLogic16的CH0、CH1、CH2通道,分別接STM32的PA3、PC13和PA9,再通過USB將電源接到電腦上,邏輯分析儀的Ground線接到STM32的GND引腳,注意高、低電平最好來自同一個電源,否則可能出現(xiàn)嚴重的毛刺,影響觀測效果。
然后在軟件界面上點擊Analyzers右邊的加號,都選擇Async Serial,設(shè)置對應(yīng)的通道號,點擊左上角的Start即可抓取在系統(tǒng)運作時的引腳波形。

抓取的波形如下圖所示,可以看到PA3、PC13分別以接近1S、3S在高低電平轉(zhuǎn)換,串口發(fā)送數(shù)據(jù)的周期是接近2S

將高低電平跳變處放大仔細看一下串口的波形。

Saleae Logic 16軟件的有數(shù)據(jù)解析功能,軟件能夠解析出框選中的時序波形00001011011對應(yīng)"h",其中:

第1個bit 0:數(shù)據(jù)起始位。
中間8個bit 00010110:有效數(shù)據(jù)位。從左往右依次為高位,即0110 1000對應(yīng)"h"的ASCII碼0x68。
第9個bit 1:停止位。
第10個bit 1:空閑位。

根據(jù)上述內(nèi)容,框選中的時序波形01010011011有效數(shù)據(jù)位10100110從左到右依次為高位,即0110 0101對應(yīng)"e"的ASCII碼0x65,所觀察到的內(nèi)容與串口通信的時序波形相符合。

四、總結(jié)

將uc/OS-III移植到stm32后,程序運行時可以把一個應(yīng)用流程分割為多個任務(wù),操作系統(tǒng)根據(jù)任務(wù)的優(yōu)先級,通過調(diào)度器使CPU分時執(zhí)行各個任務(wù),使各任務(wù)看起來是并行執(zhí)行的,減少了CPU的空閑時間,提高了CPU的利用率。另外,真實邏輯分析儀使用起來真的比Keil的邏輯分析儀使用起來方便許多,通過對這些圖形化的時序波形的觀察,能迅速定位到實際中軟件或硬件的錯誤并排除故障。

五、參考資料

Saleae Logic 16安裝文件及上手指南
提取碼:650v
STM32F103C8T6移植uC/OS-III基于HAL庫超完整詳細過程
源碼
提取碼:1234

總結(jié)

以上是生活随笔為你收集整理的基于STM32的uc/OS系统移植及用Saleae Logic 16抓取分析波形的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。