STM32
直播中

肖耳朵

12年用户 557经验值
私信 关注
[问答]

如何利STM32F407Z模拟串口去支持printf函数呢

如何利STM32F407Z模拟串口去支持printf函数呢?如何去实现其代码呢?

回帖(1)

李明

2021-11-25 15:24:38
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);                                        //!     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;
}


举报

更多回帖

发帖
×
20
完善资料,
赚取积分