UART工作原理
UART即通用異步收發(fā)器,是一種串行通信方式。數(shù)據(jù)在傳輸過程中是通過一位一位地進(jìn)行傳輸來實(shí)現(xiàn)通信的,串行通信方式具有傳輸線少,成本底等優(yōu)點(diǎn),缺點(diǎn)是速度慢。串行通信分為兩種類型:同步通信方式和異步通信方式。 但一般多用異步通信方式,主要因?yàn)榻邮芎桶l(fā)送的時鐘是可以獨(dú)立的這樣有利于增加發(fā)送與接收的靈活性。異步通信是一個字符接著一個字符傳輸,一個字符的信息由起始位、數(shù)據(jù)位、奇偶校驗(yàn)位和停止位組成。
每一個字符的傳輸靠起始位來同步,字符的前面一位是起始位,用下降沿通知收方開始傳輸,緊接著起始位之后的是數(shù)據(jù)位,傳輸時低位在前高位在后,字符本身由5~8位數(shù)據(jù)位組成。 數(shù)據(jù)位后面是奇偶校驗(yàn)位,最后是停止位,停止位是用高電平來標(biāo)記一個字符的結(jié)束,并為下一個字符的傳輸做準(zhǔn)備。停止位后面是不同長度的空閑位。停止位和空閑位都規(guī)定為高電平,這樣可以保證起始位有一個下降沿。 UART的幀格式如圖:
UART的幀格式包括線路空閑狀態(tài)(idle,高電平)、起始位(start bit,低電平)、5~8位數(shù)據(jù)位(data bits)、校驗(yàn)位(parity bit,可選)和停止位(stop bit,位數(shù)可為1、1.5、2位)。
UART模擬原理
UART的模擬方式基本就是定時器+IO口實(shí)現(xiàn)。
方案1:只打印不接收
如果在實(shí)際使用中只是為了打印log而不接收數(shù)據(jù),可以采用DWT加普通IO口的方式;
#define VCOM_BOUND 115200
#define VCOM_PIN GPIO_Pin_11
#define VCOM_PORT GPIOA
#define VCOM_PIN_HIGH VCOM_PORT->BSRR = VCOM_PIN
#define VCOM_PIN_LOW VCOM_PORT->BRR = VCOM_PIN
#define BSP_REG_DEM_CR (*(volatile unsigned int *)0xE000EDFC) //DEMCR寄存器
#define BSP_REG_DWT_CR (*(volatile unsigned int *)0xE0001000) //DWT控制寄存器
#define BSP_REG_DWT_CYCCNT (*(volatile unsigned int *)0xE0001004) //DWT時鐘計(jì)數(shù)寄存器
#define BSP_REG_DBGMCU_CR (*(volatile unsigned int *)0xE0042004)
#define DEF_BIT_00 0x01u
#define DEF_BIT_24 0x01000000u
#define BSP_BIT_DEM_CR_TRCENA DEF_BIT_24
#define BSP_BIT_DWT_CR_CYCCNTENA DEF_BIT_00
static unsigned int sys_clock = 48000000;
inline void dwt_start(void)
{
BSP_REG_DEM_CR |= (unsigned int)BSP_BIT_DEM_CR_TRCENA;
BSP_REG_DWT_CYCCNT = (unsigned int)0u; //初始化CYCCNT寄存器
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;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = VCOM_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(VCOM_PORT, &GPIO_InitStructure);
GPIO_SetBits(VCOM_PORT,VCOM_PIN);
VCOM_PIN_HIGH;
}
void vcom_put_char(char ch)
{
int i;
int dat[8];
uint32_t sys_clk, bit_width;
volatile uint32_t time_stamp;
sys_clk = sys_clock/1000000;
bit_width = 1000000*sys_clk/VCOM_BOUND;
for(i=0; i<8; i++)
{
if(ch & 0x01)
dat[i] = 1;
else
dat[i] = 0;
ch >>= 1;
}
OS_CPU_SR cpu_sr;
enter_critical();//以下代碼進(jìn)行臨界保護(hù),防止被中斷打斷造成發(fā)送誤碼
dwt_start();
VCOM_PIN_LOW; //發(fā)送起始位
time_stamp = BSP_REG_DWT_CYCCNT;
while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width));
for(i=0; i<8; i++)
{
if(dat[i])
VCOM_PIN_HIGH;
else
VCOM_PIN_LOW;
time_stamp = BSP_REG_DWT_CYCCNT;
while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //發(fā)8bit 數(shù)據(jù)位
}
VCOM_PIN_HIGH;
time_stamp = BSP_REG_DWT_CYCCNT;
while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //發(fā)停止位
dwt_stop();
exit_critical();
}
void vcom_printf(const char *fmt, ...)
{
char buf[0x80];
int i;
va_list ap;
memset(buf, 0x00, sizeof(buf));
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
i = 0;
while(buf[i])
{
vcom_put_char(buf[i]);
i++;
}
}
方案2:半雙工UART
實(shí)現(xiàn)方式: 普通定時器+普通IO口中斷+fifo
/**
*軟件串口的實(shí)現(xiàn)(IO模擬串口)
* 波特率:9600 1-8-N
* TXD : PC13
* RXD : PB14
* 使用外部中斷對RXD的下降沿進(jìn)行觸發(fā),使用定時器4按照9600波特率進(jìn)行定時數(shù)據(jù)接收。
* Demo功能: 接收11個數(shù)據(jù),然后把接收到的數(shù)據(jù)發(fā)送出去
*/
#define OI_TXD PCout(13)
#define OI_RXD PBin(14)
#define BuadRate_9600 100
u8 len = 0; //接收計(jì)數(shù)
u8 USART_buf[11]; //接收緩沖區(qū)
enum{
COM_START_BIT,
COM_D0_BIT,
COM_D1_BIT,
COM_D2_BIT,
COM_D3_BIT,
COM_D4_BIT,
COM_D5_BIT,
COM_D6_BIT,
COM_D7_BIT,
COM_STOP_BIT,
};
u8 recvStat = COM_STOP_BIT;
u8 recvData = 0;
void IO_TXD(u8 Data)
{
u8 i = 0;
OI_TXD = 0;
delay_us(BuadRate_9600);
for(i = 0; i < 8; i++)
{
if(Data&0x01)
OI_TXD = 1;
else
OI_TXD = 0;
delay_us(BuadRate_9600);
Data = Data>>1;
}
OI_TXD = 1;
delay_us(BuadRate_9600);
}
void USART_Send(u8 *buf, u8 len)
{
u8 t;
for(t = 0; t < len; t++)
{
IO_TXD(buf[t]);
}
}
void IOConfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能PB,PC端口時鐘
//SoftWare Serial TXD
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度為50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_13);
//SoftWare Serial RXD
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
EXTI_InitStruct.EXTI_Line = EXTI_Line14;
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿觸發(fā)中斷
EXTI_InitStruct.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStructure.NVIC_IRQChannel= EXTI15_10_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM4_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //時鐘使能
//定時器TIM4初始化
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時間基數(shù)單位
TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷
//中斷優(yōu)先級NVIC設(shè)置
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占優(yōu)先級1級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //從優(yōu)先級1級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級分組為組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
delay_init();
IOConfig();
TIM4_Int_Init(107, 71); //1M計(jì)數(shù)頻率
while(1)
{
if(len > 10)
{
len = 0;
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;
TIM_Cmd(TIM4, ENABLE);
}
}
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
void TIM4_IRQHandler(void)
{
if(TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
recvStat++;
if(recvStat == COM_STOP_BIT)
{
TIM_Cmd(TIM4, DISABLE);
USART_buf[len++] = recvData;
return;
}
if(OI_RXD)
{
recvData |= (1 << (recvStat - 1));
}else{
recvData &= ~(1 << (recvStat - 1));
}
}
}
上一篇:基于STM32F407的USB轉(zhuǎn)串口功能實(shí)現(xiàn)
下一篇:stm32f407 easyflash移植過程記錄
推薦閱讀最新更新時間:2025-05-21 23:34





設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 人形機(jī)器人馬拉松背后的思考,兆易創(chuàng)新如何賦能機(jī)器人產(chǎn)業(yè)
- 一種基于STM32的智能柜控制器設(shè)計(jì)
- 小型傾轉(zhuǎn)旋翼機(jī)的無刷直流電機(jī)驅(qū)動器設(shè)計(jì)
- 超高速攝影機(jī)電控系統(tǒng)設(shè)計(jì)
- 基于GPS自動授時的無線智能控制器的設(shè)計(jì)
- 基于PTR2000的無線氣象信息采集系統(tǒng)設(shè)計(jì)
- Microchip推出MEC175xB系列器件,為嵌入式控制器引入硬件 抗量子攻擊能力
- 無人飛行器機(jī)載穩(wěn)定云臺控制系統(tǒng)的設(shè)計(jì)
- 匠芯創(chuàng)推出面向具身智能高性能實(shí)時處理器M7000
- LTC2975 的典型應(yīng)用 - 具有準(zhǔn)確輸入電流和能量測量功能的 4 通道 PMBU 電源系統(tǒng)管理器
- STM32 Nucleo-64 開發(fā)板,帶 STM32WB15CC,支持 Arduino、ST Morpho 連接
- 使用 Analog Devices 的 LT1302CN8-5 的參考設(shè)計(jì)
- MC33364臨界導(dǎo)通模式反激轉(zhuǎn)換器的典型應(yīng)用電路
- AD9754-EB,用于 AD9754、14 位、125 MSPS 高性能 D/A 轉(zhuǎn)換器的評估板
- LTC1064-3,優(yōu)于用于數(shù)據(jù)通信的貝塞爾線性相位濾波器
- NCS2001SN2T1G 0.9V單電源運(yùn)放正電容乘法器典型應(yīng)用電路
- AM6TW-4803DH35Z ±3.3V 6 瓦雙路輸出 DC/DC 轉(zhuǎn)換器的典型應(yīng)用
- 使用 Analog Devices 的 LTC1538IG-AUX 的參考設(shè)計(jì)
- DC1198B-B,使用 LTM4607EV、6 至 36 Vin 至 12V、5A 高效降壓-升壓 DC/DC 模塊穩(wěn)壓器的演示板
- 吉利電池安全標(biāo)準(zhǔn)升級,“神盾金磚電池”有什么技術(shù)亮點(diǎn)?
- 中國汽車工程學(xué)會出臺全固態(tài)電池新標(biāo)準(zhǔn)
- Allegro如何用技術(shù)定義汽車電子新范式
- 恩智浦半導(dǎo)體推出汽車級開發(fā)平臺OrangeBox 2.0 旨在促進(jìn)安全的汽車通信
- 三大上市公司加碼/跨界固態(tài)電池關(guān)鍵材料!
- 一大波全固態(tài)電池新產(chǎn)品來了!
- 欣旺達(dá)/瑞浦/恩捷/力華/杜爾······12大企業(yè)電池行業(yè)新品來襲
- 新唐科技發(fā)布第四代『GerdaTM』系列,車用HMI顯示IC產(chǎn)品開始量產(chǎn)
- 寧德時代的電+Momenta的腦,“智電雙極”重構(gòu)全球汽車格局
- 一文讀懂:固態(tài)電池產(chǎn)業(yè)鏈通覽
- HTC U12+:拍照勝過華為P20 名字PK三星S9+
- ST發(fā)布《2019年可持續(xù)發(fā)展報告》
- 負(fù)債超200億元!昨日金立舉行債權(quán)人大會,公司將全面被收購
- Allegro先進(jìn)綠色能源智能解決方案亮相SNEC2019
- Mobileye/Drive.ai/特斯拉/Waymo/通用 自動駕駛最新大事件
- 應(yīng)對加征關(guān)稅,明基旗下佳世達(dá)4000萬美元將在越南設(shè)廠
- Flyme 8內(nèi)測版正式推送!粉色曬圖吸贊
- 華星光電2020年計(jì)劃推出全屏單點(diǎn)屏幕指紋
- 投660億元,微軟創(chuàng)新中心等項(xiàng)目落戶蘇州
- 重慶電網(wǎng)發(fā)展大事記