⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 STM32的GPIO口模拟串口通信
💻 C
字号:
/*
*********************************************************************************************************
*	                                  
*	模块名称 : 主程序模块。
*	文件名称 : main.c
*	版    本 : V1.0
*	说    明 : ADC采样和滤波例程。
*	修改记录 :
*		版本号  日期       作者    说明
*		v1.0    2012-11-12 armfly  ST固件库V3.5.0版本。

*
*	Copyright (C), 2010-2011, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/

#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;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -