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;
}
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;
}
举报