STM32F407Z 模拟串口(115200波特率)

PCB板打样回来发现串口1 TXD 和RXD 与CH340的TXD RXD没有交叉相连,导致串口1无法使用,于是将错就错,采用模拟串口的方式弥补了这个错误。波特率可达115200,支持printf函数。

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "stdio.h"

#define TX_L() GPIO_ResetBits(GPIOA, GPIO_Pin_10)
#define TX_H() GPIO_SetBits(GPIOA, GPIO_Pin_10)
#define RX_READ() (GPIOA->IDR & GPIO_Pin_9)

u8 recvData=0;//!<接收的一个字节数据,全局变量
u32 delayTime = 8;	//1000000/115200=8.6us  
/*!
 * @brief 	模拟串口1 TX IO口配置
 * @param	none
 * @return	none
 * @note	Tx(PA10)
 */
void MUSART1_TX_init(void)
{  
    GPIO_InitTypeDef GPIO_InitStructure;
	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_10);//TXD 空闲状态是高电平
}

/*!
 * @brief 	模拟串口1 RX IO口配置
 * @param	none
 * @return	none
 * @note	Rx(PA9)
 */
void MUSART1_RX_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//!<外部中断时钟
	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource9);

    EXTI_InitStructure.EXTI_Line=EXTI_Line9;
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿中断
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x2; //抢占优先级 2,
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x1;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
/*!
 * @brief	定时器14初始化
 * @param   定时器14复位后时钟=168M/2=84M
 * @return	NONE
 * @note	8us定时器,用于串口数据采样
 */
void Time14Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimerBaseStruct;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);//!<时钟使能
    TIM_DeInit(TIM14);					//!<Time1定时器重设缺省值
    TIM_TimerBaseStruct.TIM_Period=8;//!<设置重载寄存器初值 (设置为7,即:定时8us)
    TIM_TimerBaseStruct.TIM_Prescaler=83; 	//!<使用42M时钟,T=(83+1)*(7+1) /84= 8us
    TIM_TimerBaseStruct.TIM_ClockDivision=0;		//!<不分频
    TIM_TimerBaseStruct.TIM_CounterMode=TIM_CounterMode_Up; //!<设置计数器向上计数模式
    TIM_TimeBaseInit(TIM14,&TIM_TimerBaseStruct);


    NVIC_InitStructure.NVIC_IRQChannel=TIM8_TRG_COM_TIM14_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//定时器优先级一定要最高
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);
	
    TIM_ClearITPendingBit(TIM14, TIM_FLAG_Update);
    TIM_ITConfig(TIM14,TIM_IT_Update,ENABLE);  		//!<使能TIM1中断源
    TIM_Cmd(TIM14,DISABLE);                     	//!<禁能TIM1定时器
}

/*!
 * @brief 	模拟串口1发送一个字节
 * @param
 * @return	none
 * @note	数据低位在前高位在后
 */
void MUSART1_SendData(u8 data)//发送一个数据
{
    u8 i = 0;
    TX_L();		//!<起始位
    delay_us(delayTime);
    for(i = 0; i < 8; i++) 
	  {
        if(data & 0x01)
            TX_H();
        else
            TX_L();
        delay_us(delayTime);
        data >>= 1;
    }
    TX_H();		//!<停止位
    delay_us(delayTime);
}

u8 RevSucc=0;//接收完成标志位
u8 MUSART1_ReadData(void)//接收一个数据
{
  while(RevSucc==0){};
	RevSucc=0;
  return  recvData;
}

/*!
 * @brief	串口接收IO中断处理函数
 * @param	none
 * @return	NONE
 * @note	none
 */
void EXTI9_5_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line9) != RESET) 
		{		
			  EXTI->IMR &= 0<<9;//关闭EXTI_Line9上的中断(如果要开启中断,则反操作即可)				
        if(RX_READ() == 0x00)
				{            
                recvData = 0; 
                TIM_SetCounter(TIM14,0);	
                TIM_Cmd(TIM14, ENABLE);	//打开定时器,接收数据							  						 
        }    
        EXTI_ClearITPendingBit(EXTI_Line9);	
        
    }
}

/*!
 * @brief	定时器14中断处理函数
 * @param
 * @return	NONE
 * @note
 */

u8 count=0;

void TIM8_TRG_COM_TIM14_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM14, TIM_IT_Update) != RESET)
    {  		  	  
        if(RX_READ())
        {
            recvData |= (1 << count);//读RX电平
        }
				count++;
				if(count==8)//数据读取完成
        {
            TIM_Cmd(TIM14, DISABLE);//!<关闭定时器
					  count = 0;				
					  RevSucc=1;//接收完成				  
					  EXTI->IMR|=1<<9; //开启外部中断 准备下一次接收       
        }					   
        TIM_ClearITPendingBit(TIM14, TIM_FLAG_Update);
    }
}



#ifndef SIMULATION_USART1_H
#define SIMULATION_USART1_H


void MUSART1_TX_init(void);
void MUSART1_RX_init(void);
void Time14Init(void);
void MUSART1_SendData(u8 data);
u8 MUSART1_ReadData(void);



#endif
/****************************************************************/
/*名称: fputc */
/*功能: 重定向Printf*/
/*输入: 无*/
/*输出: 无*/
/**/
/****************************************************************/
int fputc(int ch, FILE *f)
{
    //while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
   // USART1->DR = (u8) ch;
	  MUSART1_SendData(ch);
    return ch;
}

完整MDK工程下载:https://download.csdn.net/download/qq_24835087/12025936

发布了44 篇原创文章 · 获赞 70 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_24835087/article/details/86679262
今日推荐