4周PADS强化班 HOT
林超文手把手教你学!
张飞暑期特训班
教你1000种电路设计思路
年度IP:PFC电源
张飞硬件电路之PFC全集
30天AD项目众筹
参与免费送VIP+原创视频
最全模电系列教程 NEW
运放、ADC、电磁兼容

STM32用GPIO口模拟串口通信的源程序

[复制链接]

等待验证会员

发表于 2018-7-2 08:41:21   75 查看 0 回复 显示全部楼层 倒序浏览
分享
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);
  •                         /* 清空接收缓存 */
  •                         for(i = 0; i < tmpreceivedNum; i++)
  •                                 dataReceived = 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  



标签:STM32 GPIO 串口通信

只有小组成员才能发言,加入小组>>

77个成员聚集在这个小组

加入小组

创建小组步骤

4周PADS强化班 HOT
林超文手把手教你学!
张飞暑期特训班
教你1000种电路设计思路
年度IP:PFC电源
张飞硬件电路之PFC全集
30天AD项目众筹
参与免费送VIP+原创视频
最全模电系列教程 NEW
运放、ADC、电磁兼容
关闭

站长推荐 上一条 /9 下一条

快速回复 返回顶部 返回列表
-

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

工程师杂谈

项目|工程师创意

招聘|求职}工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

ARM技术论坛

Android论坛

Linux论坛

单片机/MCU论坛

MSP430技术论坛

FPGA|CPLD|ASIC论坛

STM32/STM8技术论坛

NXP MCU 技术论坛

PIC单片机论坛

DSP论坛

瑞萨单片机论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

无线充电技术

-

硬件设计论坛

PCB设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PADS技术论坛

Protel|AD|DXP论坛

Allegro论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

Orcad论坛

-

综合技术与应用

电机控制

智能电网

光电及显示

工程资源中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

厂商专区

TI论坛

TI Deyisupport社区

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

电子展览展会专区

芯片求购|供应发布区