UART即通用异步收发器,是一种串行通信方式。数据在传输过程中是通过一位一位地进行传输来实现通信的,串行通信方式具有传输线少,成本底等优点,缺点是速度慢。串行通信分为两种类型:同步通信方式和异步通信方式。
每一个字符的传输靠起始位来同步,字符的前面一位是起始位,用下降沿通知收方开始传输,紧接着起始位之后的是数据位,传输时低位在前高位在后,字符本身由5~8位数据位组成。
UART的帧格式如图: UART的帧格式包括线路空闲状态(idle,高电平)、起始位(start bit,低电平)、5~8位数据位(data bits)、校验位(parity bit,可选)和停止位(stop bit,位数可为1、1.5、2位)。
UART模拟原理
方案1:只打印不接收
#define VCOM_BOUND 115200 #define VCOM_PORT GPIOA #define VCOM_PIN_LOW VCOM_PORT->BRR = VCOM_PIN
#define BSP_REG_DWT_CR (*(volatile unsigned int *)0xE0001000) //DWT控制寄存器 #define BSP_REG_DBGMCU_CR (*(volatile unsigned int *)0xE0042004)
#define DEF_BIT_24 0x01000000u #define BSP_BIT_DWT_CR_CYCCNTENA DEF_BIT_00 inline void dwt_start(void) BSP_REG_DEM_CR |= (unsigned int)BSP_BIT_DEM_CR_TRCENA; BSP_REG_DWT_CR |= (unsigned int)BSP_BIT_DWT_CR_CYCCNTENA; //开启CYCCNT inline void dwt_stop(void) BSP_REG_DWT_CR = 0; void vcom_pin_init(void) GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = VCOM_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_SetBits(VCOM_PORT,VCOM_PIN); }
{ int dat[8]; volatile uint32_t time_stamp;
bit_width = 1000000*sys_clk/VCOM_BOUND; { dat = 1; dat = 0; } enter_critical();//以下代码进行临界保护,防止被中断打断造成发送误码 VCOM_PIN_LOW; //发送起始位 while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); { VCOM_PIN_HIGH; VCOM_PIN_LOW; while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //发8bit 数据位 VCOM_PIN_HIGH; while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //发停止位 exit_critical(); void vcom_printf(const char *fmt, ...) char buf[0x80]; va_list ap; va_start(ap, fmt); va_end(ap);
while(buf) vcom_put_char(buf); } 方案2:半双工UART
/** * 波特率:9600 1-8-N * RXD : PB14 * Demo功能: 接收11个数据,然后把接收到的数据发送出去 #define OI_TXD PCout(13) #define BuadRate_9600 100
u8 USART_buf[11]; //接收缓冲区
COM_START_BIT, COM_D1_BIT, COM_D3_BIT, COM_D5_BIT, COM_D7_BIT, };
u8 recvData = 0;
{ OI_TXD = 0; for(i = 0; i < 8; i++) if(Data&0x01) else delay_us(BuadRate_9600); } delay_us(BuadRate_9600); void USART_Send(u8 *buf, u8 len) u8 t; { } void IOConfig(void) GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStruct; //SoftWare Serial TXD GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(GPIOC, &GPIO_InitStructure); //SoftWare Serial RXD GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure);
EXTI_InitStruct.EXTI_Line = EXTI_Line14; EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发中断 EXTI_Init(&EXTI_InitStruct);
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; }
{ NVIC_InitTypeDef NVIC_InitStructure;
//定时器TIM4初始化 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update); //中断优先级NVIC设置 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级1级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 }
{ delay_init(); TIM4_Int_Init(107, 71); //1M计数频率
{ { USART_Send(USART_buf,11); } void EXTI15_10_IRQHandler(void) if(EXTI_GetFlagStatus(EXTI_Line14) != RESET) if(OI_RXD == 0) if(recvStat == COM_STOP_BIT) recvStat = COM_START_BIT; } EXTI_ClearITPendingBit(EXTI_Line14); }
{ { recvStat++; { USART_buf[len++] = recvData; } { }else{ } }
|