STM32開發,串口和PC機通信(串口中斷、FIFO機制),安富萊+正點原子程序合併

1 概述

實驗的代碼已經上傳,無需積分。

1.1 資源概述

開發板:正點原子STM32F103 Nano開發板
CUBEMX版本:1.3.0
MDK版本:5.27
主控芯片型號:STM32F103RBT6
正點原子開發板

1.2 實現功能

1,USB連接到電腦。運行串口 軟件。
2,操作開發板上的按鍵,可以在PC機串口軟件上觀察到變化的數字。對應的LED燈翻轉。
3,在計算機鍵盤上輸入數字鍵1、2、3、4可以分別控制開發板上的4個LED指示燈。

2 軟件實現

2.1實現步驟

此次調試時發現安富萊自帶的bsp_key並不是太好用,也可能時我沒改好,怎麼改,有兩個按鍵都無法對應上,另外兩個對應上的按鍵邏輯很奇怪。於是捨棄安富萊的按鍵程序,將正點原子的按鍵程序移植過來。移植過程如下:
正點原子鍵盤支持包:key.c,key.h
安富萊鍵盤支持包:bsp _key.c,bsp_key.h
1,同時打開安富萊的工程和正點原子的工程,分別編譯通過。
2,將正點原子的key.c文件和Key.h文件直接塞到安富萊的工程中。
3,通過正點原子的工程分別找到key文件中用到的函數的定義以及相關宏定義,打開對應的文件,copy。
4,將copy的內容粘貼到安富萊工程中的key文件中。
5,編譯,並將錯誤一個個找到原因並解決。
6,在安富萊工程中,定位到bsp_key文件,查找裏邊的函數使用處,將使用到的函數,全部替換爲新增加的正點原子key文件中的函數。
7,編譯,解決報錯問題,直至沒有報錯。
8,從安富萊工程中移除bsp_key文件,再次編譯,直至改掉所有error和warning。
9,重新定義正點原子的GPIO口等,修改安富萊相關端口定義,不侷限於GPIO口,串口等。
上述步驟切記要一步一步來,慢慢改,一步到位很容易出錯,且錯誤一環套一環非常難查找。反而耽誤時間。

2.2 main()函數代碼

main()函數代碼如下,鍵盤相關部分函數借用於正點原子,其它使用安富萊自己的函數。

/*
*********************************************************************************************************
*
*	模塊名稱 : 主程序入口
*	文件名稱 : main.c
*	版    本 : V1.0
*	說    明 : 串口通信例子,和PC機超級終端軟件進行交互
*	修改記錄 :
*		版本號  日期       作者    說明
*		V1.0    2015-08-30 armfly  首發
*
*	Copyright (C), 2015-2016, 安富萊電子 www.armfly.com
*
*********************************************************************************************************
*/

#include "bsp.h"				/* 底層硬件驅動 */


/* 定義例程名和例程發佈日期 */
#define EXAMPLE_NAME	"V4-003_串口和PC機通信(串口中斷、FIFO機制)"
#define EXAMPLE_DATE	"2020-04-24"
#define DEMO_VER		"1.0"
#define key_mode 0		/*0爲按鍵不連續,1爲按鍵連續*/
static void PrintfLogo(void);
static void PrintfHelp(void);

/*
*********************************************************************************************************
*	函 數 名: main
*	功能說明: c程序入口
*	形    參:無
*	返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
	uint8_t ucKeyCode;	
	int16_t count = 0;
	uint8_t fRefresh = 0;
	uint8_t read;
	
	/*
		ST固件庫中的啓動文件已經執行了 SystemInit() 函數,該函數在 system_stm32f4xx.c 文件,主要功能是
	配置CPU系統的時鐘,內部Flash訪問時序,配置FSMC用於外部SRAM
	*/
	bsp_Init();		/* 硬件初始化 */
	
	PrintfLogo();	/* 打印例程名稱和版本等信息 */
	PrintfHelp();	/* 打印操作提示 */
	
	fRefresh = 1;
	/* 主程序大循環 */
	while (1)
	{
		bsp_Idle();		/* CPU空閒時執行的函數,在 bsp.c */
	
		/* 搖桿左右鍵(上下鍵)控制LED流動 */
		if (fRefresh)
		{
			fRefresh = 0;

			#if 0	/* 可以用 printf打印數據到串口 */
				printf("count = %6d \r\n", count);
			#else	/* 也可以用 sprintf先輸出到一個buf,然後在發送到串口 */
			{
				char buf[64];
								
				sprintf(buf, "count = %6d \r\n", count);
				
				comSendBuf(COM1, (uint8_t *)buf, strlen(buf));
			}
			#endif
		}
		
		if (comGetChar(COM1, &read))
		{
			switch (read)
			{
				case '1':
					bsp_LedToggle(1);
					break;

				case '2':
					bsp_LedToggle(2);
					break;

				case '3':
					bsp_LedToggle(3);
					break;

				case '4':
					bsp_LedToggle(4);
					break;	
			}

		}
		
		/* 處理按鍵事件 */
		ucKeyCode = KEY_Scan(key_mode);
		if (ucKeyCode != 0)
		{
			/* 有鍵按下 */
			switch (ucKeyCode)
			{
				case KEY0_PRES:		/* 按鍵0被按下 */
					count-=10;
					fRefresh = 1;
					bsp_LedToggle(1);
					break;		
				
				case KEY1_PRES:		/* 按鍵1按下 */
					count--;		
					fRefresh = 1;
					bsp_LedToggle(2);
					break;

				case KEY2_PRES:		/* 按鍵2按下 */
					count+=10;		
					fRefresh = 1;
					bsp_LedToggle(3);
					break;				
				
				case WKUP_PRES:		/* 按鍵WKUP按下 */
					count++;
					fRefresh = 1;
					bsp_LedToggle(4);
					break;
								
				default:
					break;
			}
		}
	}
}

/*
*********************************************************************************************************
*	函 數 名: PrintfHelp
*	功能說明: 打印操作提示
*	形    參:無
*	返 回 值: 無
*********************************************************************************************************
*/
static void PrintfHelp(void)
{
	printf("操作提示:\r\n");
	printf("1. 搖桿控制count計數值\r\n");
	printf("     上鍵 = +1\r\n");
	printf("     下鍵 = -1\r\n");		
	printf("     左鍵 = -10\r\n");
	printf("     右鍵 = +10\r\n");
	printf("2. PC上輸入數字1-4控制開發板上的LED指示燈\r\n");
}

/*
*********************************************************************************************************
*	函 數 名: PrintfLogo
*	功能說明: 打印例程名稱和例程發佈日期, 接上串口線後,打開PC機的超級終端軟件可以觀察結果
*	形    參:無
*	返 回 值: 無
*********************************************************************************************************
*/
static void PrintfLogo(void)
{
	printf("*************************************************************\r\n");
	printf("* 例程名稱   : %s\r\n", EXAMPLE_NAME);	/* 打印例程名稱 */
	printf("* 例程版本   : %s\r\n", DEMO_VER);		/* 打印例程版本 */
	printf("* 發佈日期   : %s\r\n", EXAMPLE_DATE);	/* 打印例程日期 */

	/* 打印ST固件庫版本,宏定義在 stm32f4xx.h 文件 */
	printf("* 固件庫版本 : %d.%d.%d\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
			__STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);

	/* 打印 CMSIS 版本. 宏定義在 core_cm4.h 文件 */
	printf("* CMSIS版本  : %X.%02X\r\n", __CM3_CMSIS_VERSION_MAIN, __CM3_CMSIS_VERSION_SUB);

	printf("* \r\n");	/* 打印一行空格 */
	printf("* QQ    : 1295744630 \r\n");
	printf("* Email : [email protected] \r\n");
	printf("* Copyright www.armfly.com 安富萊電子\r\n");
	printf("*************************************************************\r\n");
}

/***************************** 安富萊電子 www.armfly.com (END OF FILE) *********************************/

2.3 正點原子鍵盤連按和不連按函數說明

u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按鍵按鬆開標誌
	if(mode)key_up=1;  //支持連按		  
	if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
	{
		bsp_DelayMS(10);//去抖動 
		key_up=0;
		if(KEY0==0)return KEY0_PRES;
		else if(KEY1==0)return KEY1_PRES;
		else if(KEY2==0)return KEY2_PRES;
		else if(WK_UP==1)return WKUP_PRES; 
	}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1; 	     
	return 0;// 無按鍵按下
}

第三行,定義了一個靜態變量,static,這個函數在程序運行時,第一次調用函數時,後面跟着key_up=1纔有效。後面不管調用了多少次此定義的key_up=1不再生效,即使被其它地方賦值了其它數。通過這個功能實現了連按和不連按的功能。實驗證實,當static這個類型刪除後,不管mode是0還是1,都是連按。

3 實驗結果

串口打印結果
串口打印結果
發送1234時,全部的四個燈點亮亮燈
再次發送1234時,四個燈全滅
滅燈操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章