STM32 一般有4、5個串口,足夠使用,這個給想擴一個串口的參考
/*
****************************************************************************
* 例程名稱 : Ex004-使用GPIO口模擬串口通信
* 例程版本 : V2.0
* ST固件庫版本 :V3.5.0
* 作 者 : armfly
* 發布日期 : 10-16
* 開發環境 : KEIL的uVision V3.70、uVision V4.13、IAR的EWARM V5.30
*
* 修改記錄 :
* 2010-09-27 發布V1.0版本,固件庫為V3.1.2
* 2011-03-20 發布V1.1版本,固件庫為V3.4.0
* 2011-11-16 發布2.0版本,固件庫為V3.5.0,優化工程結構,打印信息改為中文
*
*********************************************************************************************************
*/
【1】例程介紹
這個例子演示如何使用兩個GPIO口模擬串口通信,波特率9600,8位數據位,1位停止位。
IO口的選擇:
(1)為方便連接至PC的串口,仍選用PA9與PA10,不過這里只將它們當作變通的IO口使用。PA9對應TXD,PA10對應RXD的功能。
模擬串口發送:
(1)TIM3用于產生1bit[104uS]的延時
模擬串口接收:
(1)PA10上的下降沿將觸發外部中斷,這標志著“起始位0”的到來。在對應的中斷服務程序中,會立即關閉該外部中斷,以
防后續的“數據位”誤觸發本中斷。
(2)TIM1用于產生104uS的中斷,定時去讀取PA10上的電平,直至接收到一個完整的字節數據。
(3)在接收到一個完整的字節數據之后,開啟TIM2,它的作用是判斷是否接收到了全部的數據。
請用串口線將開發板的COM1口連接到PC機的串口(或者USB串口),然后打開串口調試助手(推薦使用作者為聶小猛的那款,它
可以顯示返回至PC的中文字符),可以在軟件界面看到例程的運行信息。
程序具有如下功能:
- 復位后打印例程基本信息
- 在接收完PC發送下去的數據后,將它們全部返回。
程序執行結果如下:
Hello,C!
*************************************************************
* 例程名稱 : GPIO口模擬串口
* 例程版本 : 1.0
* 發布日期 : 11-12
* 固件庫版本 : 3.5.0
*************************************************************
請通過串口調試助手發送數據,本例程會將這些數據通過串口原樣返回。
對于Keil MDK,為了避免中文字符串告警,需要在C/C++編譯選項中增加 --diag_suppress=870 參數。
本程序支持在CPU內部Flash、CPU內部RAM和CPU外部RAM調試。在CPU內部RAM和CPU外部SRAM調試時,無需切換開發板上的
啟動模式撥碼開關。請將撥碼開關撥到Flash位置。
【2】例程文件夾說明
├─Libraries : 存放第3方提供的庫或其源代碼,這些代碼一般是成熟的并經過驗證的代碼。
│ ├─CMSIS : Cortex微控制器軟件接口程序,這是ST官方提供的固件庫的一部分。
│ └─STM32F10x_StdPeriph_Driver : STM32F10x系列MCU的固件庫源代碼,這是ST官方提供的固件庫的核心代碼。
│
├─User : 這里存放用戶自己編寫的源代碼
│ └─bsp : 板級支持包(Board Surport Packet),也就是硬件底層驅動程序
│
└─project : 這里存放各類開發工具的工程文件
├─EWARMv5 : IAR公司EWARM工程文件
├─MDK-ARM(uV3) :KEIL的MDK工程文件,uVision3版本。uV3不能打開uV4版本的工程。
└─MDK-ARM(uV4) : KEIL的MDK工程文件,uVision4版本。uV4可以打開uV3版本的工程。
【3】工程中源代碼分組說明
└─Flash : Target名稱:Flash、CpuRAM 或 ExtSRAM
├─USER : 用戶程序
├─MDK-ARM : 和IDE開發工具相關的啟動代碼(匯編)。MDK表示KEIL的IDE,EWARMv5表示IAR的IDE
├─StdPeriph_Driver : STM32F10x系列MCU的固件庫源代碼
├─CMSIS : Cortex微控制器軟件接口程序源代碼
└─Doc : 存放一些文檔
【4】工程中Target說明
Flash : 目標代碼定位在CPU內部Flash。ROM地址: 0x08000000 RAM地址: 0x20000000
CpuRAM : 目標代碼定位在CPU內部RAM。 ROM地址: 0x20000000 RAM地址: 0x20008000
ExtSRAM : 目標代碼定位在外部SRAM。 ROM地址: 0x68000000 RAM地址: 0x20000200 (前面0x200空間存放
中斷向量表)
- /*
- *********************************************************************************************************
- *
- * 模塊名稱 : 主程序模塊。
- * 文件名稱 : main.c
- * 版 本 : V1.0
- * 說 明 : ADC采樣和濾波例程。
- * 修改記錄 :
- * 版本號 日期 作者 說明
- *
- *********************************************************************************************************
- */
- #include "stm32f10x.h" /* 如果要用ST的固件庫,必須包含這個文件 */
- #include <stdio.h> /* 因為用到了printf函數,所以必須包含這個文件 */
- /* 定義例程名和例程發布日期 */
- #define EXAMPLE_NAME "GPIO口模擬串口"
- #define EXAMPLE_DATE "2012-11-12"
- #define DEMO_VER "1.0"
- #define TXD_high() GPIO_SetBits(GPIOA, GPIO_Pin_9)
- #define TXD_low() GPIO_ResetBits(GPIOA, GPIO_Pin_9)
- #define BaudRateUsed 9600
- #define SendingDelay 104
- /* 僅允許本文件內調用的函數聲明 */
- static void PrintfLogo(void);
- static void GPIO_Configuration(void);
- static void Delay_Ms(__IO uint32_t nTime);
- static void EXTI_Configuration(void);
- static void TIM1_Configuration(void);
- static void TIM2_Configuration(void);
- static void TIM3_Configuration(void);
- static void PrintfAnswer(void);
- /* 外部文件可以調用的函數聲明 */
- void SendOneByte(uint8_t datatoSend);
- __IO uint32_t TimingDelay;
- uint8_t dataReceived[100];
- uint8_t Logo[]={"Hello, C!\r\n"};
- __IO uint8_t receivedFlag;
- __IO uint8_t receivedNum, tmpreceivedNum;
- uint16_t g_usAdcValue; /* ADC 采樣值的平均值 */
- /*
- *********************************************************************************************************
- * 函 數 名: main
- * 功能說明: c程序入口
- * 形 參:無
- * 返 回 值: 錯誤代碼(無需處理)
- *********************************************************************************************************
- */
- int main(void)
- {
- /*
- 由于ST固件庫的啟動文件已經執行了CPU系統時鐘的初始化,所以不必再次重復配置系統時鐘。
- 啟動文件配置了CPU主時鐘頻率、內部Flash訪問速度和可選的外部SRAM FSMC初始化。
-
- 系統時鐘缺省配置為72MHz,如果需要更改,可以修改:
- \Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\system_stm32f10x.c
- 中配置系統時鐘的宏。
- */
- uint8_t i;
- /* IO配置 */
- GPIO_Configuration();
- /* 配置外部中斷 */
- EXTI_Configuration();
- /* TIM1初始化,用于接收 */
- TIM1_Configuration();
- /* TIM2初始化,用于判斷數據是否接收完成 */
- TIM2_Configuration();
- /* TIM3初始化,用于發送 */
- TIM3_Configuration();
- /* 直接調用模擬串口發送函數 */
- SendOneByte('H');
- SendOneByte('e');
- SendOneByte('l');
- SendOneByte('l');
- SendOneByte('o');
- SendOneByte(',');
- SendOneByte('C');
- SendOneByte('!');
- SendOneByte('\r');
- SendOneByte('\n');
- /* 打印例程Logo,間接調用模擬串口發送函數 */
- PrintfLogo();
-
- /* 進入主程序循環體 */
- while (1)
- {
- if(receivedFlag)
- {
- /* 清除接收完成標志位 */
- receivedFlag = 0;
- /* 返回接收到的數據 */
- for(i = 0; i < tmpreceivedNum; i++)
- SendOneByte(dataReceived[i]);
- /* 清空接收緩存 */
- for(i = 0; i < tmpreceivedNum; i++)
- dataReceived[i] = 0;
- /* 返回模擬對話數據 */
- PrintfAnswer();
- /* 接收數據長度清零 */
- tmpreceivedNum = 0;
- }
- }
- }
- /*
- *********************************************************************************************************
- * 函 數 名: GPIO_Configuration
- * 功能說明: 配置PA9為TXD,PA10做RXD
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- static void GPIO_Configuration(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- /* 使能 GPIOA clock */
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
- /* 防止上電后的誤判 */
- GPIO_SetBits(GPIOA, GPIO_Pin_9);
- /* 配置PA9為推挽輸出 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- /* 配置PA10為浮空輸入 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
- /*
- *********************************************************************************************************
- * 函 數 名: EXTI_Configuration
- * 功能說明: 配置PA10上的下降沿觸發外部中斷
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- static void EXTI_Configuration(void)
- {
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- /* Enable the AFIO Clock */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
- /* Configure Button EXTI line */
- EXTI_InitStructure.EXTI_Line = EXTI_Line10;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- /* Enable and set Button EXTI Interrupt to the lowest priority */
- NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /*
- *********************************************************************************************************
- * 函 數 名: TIM1_Configuration
- * 功能說明: 配置TIM1
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- static void TIM1_Configuration(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
- /* Time base configuration */
- TIM_TimeBaseStructure.TIM_Period = SendingDelay -1;
- TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
- TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update);
-
- /* 開啟TIM1的中斷 */
- TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
-
- /* 選擇TIM2的中斷通道 */
- NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
-
- /* 搶占式中斷優先級設置為0 */
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
-
- /* 響應式中斷優先級設置為0 */
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
-
- /* 使能中斷 */
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /*
- *********************************************************************************************************
- * 函 數 名: TIM2_Configuration
- * 功能說明: 配置TIM1
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- static void TIM2_Configuration(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
- /* Time base configuration */
- TIM_TimeBaseStructure.TIM_Period = 1000 - 1;
- TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
- TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
-
- /* 開啟TIM1的中斷 */
- TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
-
- /* 選擇TIM2的中斷通道 */
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
-
- /* 搶占式中斷優先級設置為0 */
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-
- /* 響應式中斷優先級設置為0 */
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
-
- /* 使能中斷 */
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /*
- *********************************************************************************************************
- * 函 數 名: TIM3_Configuration
- * 功能說明: 配置TIM1
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- static void TIM3_Configuration(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
- /* Time base configuration */
- TIM_TimeBaseStructure.TIM_Period = 65535 - 1;
- TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
- TIM_Cmd(TIM3,ENABLE);
- }
- /*
- *********************************************************************************************************
- * 函 數 名: Delay_Ms
- * 功能說明: 延時
- * 形 參:nTime,單位為uS
- * 返 回 值: 無
- *********************************************************************************************************
- */
- void Delay_Ms(__IO uint32_t nTime)
- {
- uint16_t tmp;
- tmp = TIM_GetCounter(TIM3);
-
- if(tmp + nTime <= 65535)
- while( (TIM_GetCounter(TIM3) - tmp) < nTime );
- else
- {
- TIM_SetCounter(TIM3, 0);
- while( TIM_GetCounter(TIM3) < nTime );
- }
-
- }
- /*
- *********************************************************************************************************
- * 函 數 名: SendOneByte
- * 功能說明: 模擬串口發送一字節數據
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- void SendOneByte(uint8_t datatoSend)
- {
- uint8_t i, tmp;
- /* Start bit */
- TXD_low();
- Delay_Ms(SendingDelay);
- for(i = 0; i < 8; i++)
- {
- tmp = (datatoSend >> i) & 0x01;
- if(tmp == 0)
- {
- TXD_low();
- Delay_Ms(SendingDelay); //0
- }
- else
- {
- TXD_high();
- Delay_Ms(SendingDelay); //1
- }
- }
-
- /* Stop bit */
- TXD_high();
- Delay_Ms(SendingDelay);
- }
- /*
- *********************************************************************************************************
- * 函 數 名: 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固件庫版本,這3個定義宏在stm32f10x.h文件中 */
- printf("* 固件庫版本 : %d.%d.%d\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
- __STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);
- printf("* \n\r"); /* 打印一行空格 */
- printf("* QQ : 1295744630 \r\n");
- printf("* Email : armfly@qq.com \r\n");
- printf("* Copyright www.armfly.com 安富萊電子\r\n");
- printf("*************************************************************\r\n");
- printf("請通過串口調試助手發送數據,本例程會將這些數據通過串口原樣返回。\r\n\r\n");
- }
- /*
- *********************************************************************************************************
- * 函 數 名: PrintfLogo
- * 功能說明: 隨機打印模擬對話
- * 形 參:無
- * 返 回 值: 無
- *********************************************************************************************************
- */
- static void PrintfAnswer(void)
- {
- uint16_t tmp;
- tmp = TIM_GetCounter(TIM3);
- switch(tmp % 9)
- {
- case 0:
- printf("\r\n--雷工,數據已悉數返回,掰掰手指頭,有未丟?\r\n");
- break;
- case 1:
- printf("\r\n--報告雷工,我的工作完了,輪到你檢查了!\r\n");
- break;
- case 2:
- printf("\r\n--咦,還沒有錯?\r\n");
- break;
- case 3:
- printf("\r\n--靠,還不出錯?\r\n");
- break;
- case 4:
- printf("\r\n--雷工,要不,再試試?\r\n");
- break;
- case 5:
- printf("\r\n--小雷,檢查過沒有,數據對不對?\r\n");
- break;
- case 6:
- printf("\r\n--小雷,數據對不對?\r\n");
- break;
- case 7:
- printf("\r\n--怎么樣,小雷,驗收通過了沒?\r\n");
- break;
- case 8:
- printf("\r\n--小雷,我的支付寶是168 168 168 168\r\n");
- break;
- default:
- printf("\r\n--這句不可能出現在屏幕上\r\n");
- break;
- }
- }
復制代碼 源碼下載:
STM模擬串口.7z
(489.86 KB, 下載次數: 319)
2018-2-2 17:12 上傳
點擊文件名下載附件
模擬串口
|