0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于N32G435的高負(fù)載串口通信

國(guó)民技術(shù)股份有限公司 ? 2022-09-22 17:28 ? 次閱讀

一、前言

單片機(jī)中,USART通信是最常用也是最先去接觸的串口外設(shè),在小數(shù)據(jù)量應(yīng)用中一般不需要考慮USART串口(以下簡(jiǎn)稱為串口)的高負(fù)載能力,比如打印一下log,接收幾個(gè)其他設(shè)備的指令或者發(fā)送幾個(gè)指令控制其他設(shè)備。但是在高速的大數(shù)據(jù)量的通信場(chǎng)合,串口可能會(huì)承載較高的數(shù)據(jù)負(fù)載,如果不合理地進(jìn)行單片機(jī)的資源利用,則有可能造成各種問(wèn)題。比如使用串口接收中斷接收大量的數(shù)據(jù),頻繁地進(jìn)入中斷,會(huì)占用太多的CPU資源。這時(shí)可能會(huì)想到【空閑中斷+DMA傳輸完成中斷】的方式接收大量數(shù)據(jù),但是這是一個(gè)極具風(fēng)險(xiǎn)的行為,假設(shè)一下,DMA數(shù)據(jù)傳輸結(jié)束之后,此時(shí)CPU開(kāi)始讀取DMA緩存中的數(shù)據(jù),此時(shí)又有新的數(shù)據(jù)進(jìn)來(lái),新的數(shù)據(jù)就會(huì)覆蓋之前的數(shù)據(jù)導(dǎo)致異常。

二、如何啟用串口的DMA功能

在討論如何實(shí)現(xiàn)串口的高負(fù)載通信之前,我們得先明白如何啟用串口的DMA通信。

DMA(DirectMemoryAccess)直接儲(chǔ)存器訪問(wèn),是一個(gè)CPU用于數(shù)據(jù)從一個(gè)地址空間到另一個(gè)地址空間的搬運(yùn)組件,該過(guò)程無(wú)需CPU的干預(yù),不占用CPU的資源,可以使單片機(jī)這種單線程CPU實(shí)現(xiàn)“偽多線程”。只需在數(shù)據(jù)搬運(yùn)結(jié)束后通知CPU即可。

在國(guó)民技術(shù)的資料中是有串口+DMA的例程的,但是官方為了用戶調(diào)試方便,例程相對(duì)簡(jiǎn)單,就是實(shí)現(xiàn)了兩個(gè)MCU串口間的DMA通信,在開(kāi)發(fā)時(shí)具有一定借鑒意義,但是不具備高負(fù)載能力,同時(shí)移植性不是很好,這里我在例程的基礎(chǔ)上進(jìn)行簡(jiǎn)化,同時(shí)例程不具備的功能也會(huì)一一展開(kāi)。

1.串口+DMA發(fā)送

#defineTxBufferSize1 (countof(TxBuffer1) - 1)

#definecountof(a) (sizeof(a) / sizeof(*(a)))

USART_InitTypeUSART_InitStructure;

uint8_tTxBuffer1[20] ={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a};

首先是定義一些相關(guān)的變量,數(shù)據(jù)和結(jié)構(gòu)體啥的,TxBufferSize1發(fā)送數(shù)量,TxBuffer1[20]發(fā)送的數(shù)組。

/**

*[url=home.php?mod=space&uid=247401]@brief[/url] Configures thedifferent system clocks.

*/

voidRCC_Configuration(void)

{

/*DMA clock enable */

RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA,ENABLE);

/*Enable GPIO clock */

RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB,ENABLE);

/*Enable USARTy and USARTz Clock */

RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1,ENABLE);

}

/**

*[url=home.php?mod=space&uid=247401]@brief[/url] Configures thedifferent GPIO ports.

*/

voidGPIO_Configuration(void)

{

GPIO_InitTypeGPIO_InitStructure;

/*Initialize GPIO_InitStructure */

GPIO_InitStruct(&GPIO_InitStructure);

/*Configure USARTy Tx as alternate function push-pull */

GPIO_InitStructure.Pin = GPIO_PIN_6;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Alternate= GPIO_AF0_USART1;

GPIO_InitPeripheral(GPIOB,&GPIO_InitStructure);

/*Configure USARTy Rx as alternate function push-pull and pull-up */

GPIO_InitStructure.Pin = GPIO_PIN_7;

GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up;

GPIO_InitStructure.GPIO_Alternate= GPIO_AF0_USART1;

GPIO_InitPeripheral(GPIOB,&GPIO_InitStructure);

}

對(duì)相關(guān)的時(shí)鐘和串口的引腳進(jìn)行初始化,這里是直接用的官方例程,只不過(guò)將官方例程的宏定義換成了實(shí)際的值,便于看代碼,不然還需跳轉(zhuǎn),但是官方的例程這方面的可移植性會(huì)更好。

voidDMA_Configuration(void)

{

DMA_InitTypeDMA_InitStructure;

/*USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */

DMA_DeInit(DMA_CH4);

DMA_StructInit(&DMA_InitStructure);

DMA_InitStructure.PeriphAddr = (USART1_BASE + 0x04);

DMA_InitStructure.MemAddr = (uint32_t)TxBuffer1;

DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;

DMA_InitStructure.BufSize = TxBufferSize1;

DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;

DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;

DMA_InitStructure.PeriphDataSize= DMA_PERIPH_DATA_SIZE_BYTE;

DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;

DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH;

DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;

DMA_Init(DMA_CH4,&DMA_InitStructure);

DMA_RequestRemap(DMA_REMAP_USART1_TX,DMA, DMA_CH4, ENABLE);

}

DMA的初始化采用NORMAL模式,即只發(fā)送一次,當(dāng)計(jì)數(shù)器為0時(shí)便不再搬運(yùn)數(shù)據(jù)。

voidUART_Init(USART_Module* USARTx,uint32_t BaudRate)

{

/*USARTy and USARTz configuration ---------------------------*/

USART_StructInit(&USART_InitStructure);

USART_InitStructure.BaudRate = BaudRate;

USART_InitStructure.WordLength = USART_WL_8B;

USART_InitStructure.StopBits = USART_STPB_1;

USART_InitStructure.Parity = USART_PE_NO;

USART_InitStructure.HardwareFlowControl= USART_HFCTRL_NONE;

USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;

/*Configure USARTy and USARTz */

USART_Init(USARTx,&USART_InitStructure);

/*Enable USARTy DMA Rx and TX request */

USART_EnableDMA(USARTx,USART_DMAREQ_RX | USART_DMAREQ_TX, ENABLE);

/*Enable the USARTy and USARTz */

USART_Enable(USARTx,ENABLE);

}

串口的初始化。

voidDMA_send(uint8_t* pBuffer,uint16_t BufferLength)

{

DMA_EnableChannel(DMA_CH4,DISABLE);

DMA_SetCurrDataCounter(DMA_CH4,BufferLength);

DMA_EnableChannel(DMA_CH4,ENABLE);

while(USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET)

{

}

}

DMA的發(fā)送函數(shù),先失能DMA通道,再重新設(shè)置傳輸長(zhǎng)度,再使能DMA通道,這里是檢測(cè)while是檢測(cè)串口的發(fā)送完成編制位,在官方的demo中檢測(cè)的是DMA的通道完成標(biāo)志,這個(gè)在這里面是不可以的,因?yàn)镈MA的搬運(yùn)速度是遠(yuǎn)大于串口的通信速度的,如果檢測(cè)DMA通道完成標(biāo)志,會(huì)導(dǎo)致DMA已經(jīng)將數(shù)據(jù)搬運(yùn)到串口的數(shù)據(jù)寄存器,但是因?yàn)榇诘乃俣炔粔颍瑢?dǎo)致此時(shí)數(shù)據(jù)還未送出,而因?yàn)槔讨谎h(huán)一次,在測(cè)試?yán)虝r(shí)看不出問(wèn)題,但是這里會(huì)出問(wèn)題。

intmain(void)

{

/*System Clocks Configuration */

RCC_Configuration();

/*Configure the GPIO ports */

GPIO_Configuration();

/*Configure the DMA */

DMA_Configuration();

UART_Init(USART1,115200);

while(1)

{

DMA_send(TxBuffer1,20);

Delay(10000000);

}

}

最后在主函數(shù)調(diào)用各初始化函數(shù),在while(1)中循環(huán)發(fā)送便可實(shí)現(xiàn)最簡(jiǎn)單的串口+DMA發(fā)送。

875f42f4-39f0-11ed-b180-dac502259ad0.png

2.串口+DMA接收

在上面發(fā)送的基礎(chǔ)上我們加上DMA的接收功能,此處需要解釋一下下面的操作:為了對(duì)應(yīng)手冊(cè),上面的串口發(fā)送DMA通道原來(lái)是CH4,我下面全部改成CH1。

uint8_tRxBuffer1[20];

定義一個(gè)數(shù)組用于接收串口數(shù)據(jù)。

USART_ConfigInt(USARTx,USART_INT_IDLEF, ENABLE);

添加串口中斷定義。

voidNVIC_Configuration(void)

{

NVIC_InitTypeNVIC_InitStructure;

/*Enable the USARTz Interrupt */

NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;

NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

添加NVIC配置。

voidDMA_Configuration(void)

{

DMA_InitTypeDMA_InitStructure;

/*USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */

DMA_DeInit(DMA_CH1);

DMA_StructInit(&DMA_InitStructure);

DMA_InitStructure.PeriphAddr= (USART1_BASE + 0x04);

DMA_InitStructure.MemAddr= (uint32_t)TxBuffer1;

DMA_InitStructure.Direction= DMA_DIR_PERIPH_DST;

DMA_InitStructure.BufSize= TxBufferSize1;

DMA_InitStructure.PeriphInc= DMA_PERIPH_INC_DISABLE;

DMA_InitStructure.DMA_MemoryInc= DMA_MEM_INC_ENABLE;

DMA_InitStructure.PeriphDataSize= DMA_PERIPH_DATA_SIZE_BYTE;

DMA_InitStructure.MemDataSize= DMA_MemoryDataSize_Byte;

DMA_InitStructure.CircularMode= DMA_MODE_NORMAL;

DMA_InitStructure.Priority= DMA_PRIORITY_VERY_HIGH;

DMA_InitStructure.Mem2Mem= DMA_M2M_DISABLE;

DMA_Init(DMA_CH1,&DMA_InitStructure);

DMA_RequestRemap(DMA_REMAP_USART1_TX,DMA, DMA_CH1, ENABLE);

DMA_DeInit(DMA_CH2);

DMA_InitStructure.PeriphAddr= (USART1_BASE + 0x04);

DMA_InitStructure.MemAddr= (uint32_t)RxBuffer1;

DMA_InitStructure.Direction= DMA_DIR_PERIPH_SRC;

DMA_InitStructure.BufSize= TxBufferSize1;

DMA_Init(DMA_CH2,&DMA_InitStructure);

DMA_RequestRemap(DMA_REMAP_USART1_RX,DMA, DMA_CH2, ENABLE);

}

添加DMA的接收,并將通道設(shè)置為CH2。

voidDMA_Revice(uint16_t BufferLength)

{

DMA_EnableChannel(DMA_CH2,DISABLE);

DMA_SetCurrDataCounter(DMA_CH2,BufferLength);

DMA_EnableChannel(DMA_CH2,ENABLE);

}

添加DMA接收函數(shù)

voidUSART1_IRQHandler(void)

{

if(USART_GetIntStatus(USART1, USART_INT_IDLEF) != RESET)

{

/*軟件先讀USART_STS,再讀USART_DAT清除空閑中斷標(biāo)志。*/

USART1->STS;

USART1->DAT;

for(inti=0;i<20;i++)

{

TxBuffer1[i]= RxBuffer1[i];

}

DMA_send(20);

DMA_Revice(20);

}

}

添加串口中斷函數(shù),在串口中斷函數(shù)中將接收的數(shù)據(jù)傳給DMA發(fā)送數(shù)組,再通過(guò)DMA的方式發(fā)送出來(lái)用于校驗(yàn)結(jié)果。

87819e58-39f0-11ed-b180-dac502259ad0.png

通過(guò)串口助手可觀測(cè)數(shù)據(jù)正確。至此,常見(jiàn)的串口+DMA的發(fā)送與接收完成。后文將實(shí)現(xiàn)高負(fù)載的通信。

三、高負(fù)載情況下的DMA如何實(shí)現(xiàn)

在串口數(shù)據(jù)量較大時(shí),一般使用雙BUF,很多單片機(jī)有硬件雙緩沖,DMA的目標(biāo)儲(chǔ)存區(qū)域有兩個(gè),當(dāng)一次完整的數(shù)據(jù)傳輸結(jié)束后,也就是counter值變?yōu)?時(shí),DMA會(huì)自動(dòng)將數(shù)據(jù)指向另一塊區(qū)域。這樣用戶就有時(shí)間去處理剛存滿的buf,而不會(huì)被覆蓋。就是“乒乓緩存”。

普通DMA

8794a61a-39f0-11ed-b180-dac502259ad0.png

DMA雙緩沖

87b6f90e-39f0-11ed-b180-dac502259ad0.png

大致流程如下:

1.串口有數(shù)據(jù)到來(lái),DMA現(xiàn)將數(shù)據(jù)儲(chǔ)存在內(nèi)存1,完成后通知CPU過(guò)來(lái)處理數(shù)據(jù)。

2.此時(shí)DMA不停下,開(kāi)始將后續(xù)的數(shù)據(jù)搬運(yùn)到內(nèi)存2。

3.內(nèi)存2的數(shù)據(jù)搬運(yùn)完成,通知CPU開(kāi)始處理內(nèi)存2中的數(shù)據(jù)。

4.如果數(shù)據(jù)傳輸還未結(jié)束,此時(shí)DMA會(huì)將數(shù)據(jù)儲(chǔ)存在內(nèi)存1。如此循環(huán),直至沒(méi)有數(shù)據(jù)到來(lái)。

但是遺憾的是N32G435這塊芯片不具備雙緩沖模式,那么我們可以主動(dòng)控制DMA跳轉(zhuǎn)內(nèi)存區(qū)域。利用“傳輸過(guò)半中斷”來(lái)模擬雙緩沖模式。

大致流程如下:

1.DMA完成搬運(yùn)一半的數(shù)據(jù)時(shí),產(chǎn)生一個(gè)傳輸過(guò)半中斷,此時(shí)我們讓CPU來(lái)處理上一半數(shù)據(jù)。

2.DMA數(shù)據(jù)搬運(yùn)未停止,此時(shí)繼續(xù)搬運(yùn)后一半數(shù)據(jù),此操作不會(huì)影響前面一半的數(shù)據(jù)處理。

3.DMA數(shù)據(jù)搬運(yùn)完,觸發(fā)傳輸完成中斷,這時(shí)CPU可以處理后半數(shù)據(jù)。

4.如果數(shù)據(jù)傳輸還未結(jié)束,DMA繼續(xù)將數(shù)據(jù)向前半搬運(yùn),如此循環(huán)。

87c9e38e-39f0-11ed-b180-dac502259ad0.png

代碼講解如下:

以下代碼完整流程如下:

1.配置串口波特率2.5M,DMA的BufSize設(shè)置為40,開(kāi)啟傳輸過(guò)半中斷,傳輸完成中斷,串口空閑中斷。

2.啟動(dòng)DMA接收。

3.通過(guò)串口助手發(fā)送80個(gè)數(shù)據(jù)到串口。

4.當(dāng)DMA接收數(shù)組接收到20個(gè)數(shù)據(jù)觸發(fā)傳輸過(guò)半中斷,跳轉(zhuǎn)中斷函數(shù)將20個(gè)數(shù)據(jù)存放到數(shù)組中。

5.此時(shí)DMA仍在運(yùn)行,但是數(shù)據(jù)存放在DMA接收數(shù)組的后20個(gè)地址空間。

6.當(dāng)DMA接收數(shù)組填滿,觸發(fā)DMA傳輸完成中斷,跳轉(zhuǎn)中斷函數(shù)將后20個(gè)數(shù)據(jù)保存,此時(shí)DMA一共搬運(yùn)了40個(gè)數(shù)據(jù)。

7.DMA繼續(xù)搬運(yùn)數(shù)據(jù)到接收數(shù)組里,此時(shí)會(huì)覆蓋之前的前二十個(gè)數(shù)據(jù),跳轉(zhuǎn)到步驟4.

8.接收完80個(gè)數(shù)據(jù),此時(shí)觸發(fā)串口空閑中斷,將接收到的數(shù)據(jù)打印出來(lái)。

在上面代碼基礎(chǔ)上做如下操作:

1.將DMACH2通道設(shè)置為循環(huán)模式,測(cè)試階段將BufSize設(shè)置為40,開(kāi)啟傳輸過(guò)半中斷和傳輸完成中斷。同時(shí)為了測(cè)試高速場(chǎng)景,串口波特率設(shè)置為2.5M:

DMA_DeInit(DMA_CH2);

DMA_InitStructure.PeriphAddr= (USART1_BASE + 0x04);

DMA_InitStructure.MemAddr= (uint32_t)buffer;

DMA_InitStructure.Direction= DMA_DIR_PERIPH_SRC;

DMA_InitStructure.BufSize= 40;

DMA_InitStructure.CircularMode= DMA_MODE_CIRCULAR;

DMA_Init(DMA_CH2,&DMA_InitStructure);

DMA_RequestRemap(DMA_REMAP_USART1_RX,DMA, DMA_CH2, ENABLE);

DMA_ConfigInt(DMA_CH2,DMA_INT_HTX,ENABLE);//半傳輸中斷

DMA_ConfigInt(DMA_CH2,DMA_INT_TXC,ENABLE);//傳輸完成中斷

DMA_ClearFlag(DMA_FLAG_HT2,DMA);//清除標(biāo)志位,避免第一次傳輸出錯(cuò)

DMA_ClearFlag(DMA_FLAG_TC2,DMA);

DMA_ClrIntPendingBit(DMA_INT_HTX2,DMA);

DMA_ClrIntPendingBit(DMA_INT_TXC2,DMA);

2.NVIC設(shè)置DMA通道中斷

voidNVIC_Configuration(void)

{

NVIC_InitTypeNVIC_InitStructure;

/*Enable the USARTz Interrupt */

NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;

NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel= DMA_Channel2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;

NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

3.添加DMA的CH2中斷函數(shù),num為全局變量,目的是將所有的數(shù)據(jù)保存進(jìn)buf數(shù)組:

voidDMA_Channel2_IRQHandler(void)

{

//傳輸半滿

if(DMA_GetIntStatus(DMA_INT_HTX2,DMA)== SET)

{

DMA_ClrIntPendingBit(DMA_INT_HTX2,DMA);

DMA_ClearFlag(DMA_FLAG_HT2,DMA);

for(inti=0;i<20;i++)

{

buf[num]= buffer[i];

num++;

}

}

//傳輸滿

if(DMA_GetIntStatus(DMA_INT_TXC2,DMA)== SET)

{

DMA_ClrIntPendingBit(DMA_INT_TXC2,DMA);

DMA_ClearFlag(DMA_FLAG_TC2,DMA);

for(inti=20;i<40;i++)

{

buf[num]= buffer[i];

num++;

}

}

}

4.在串口空閑中斷中將收到的數(shù)據(jù)全部打印出來(lái)。

voidUSART1_IRQHandler(void)

{

if(USART_GetIntStatus(USART1, USART_INT_IDLEF) != RESET)

{

/*軟件先讀USART_STS,再讀USART_DAT清除空閑中斷標(biāo)志。*/

USART1->STS;

USART1->DAT;

for(inti=0;i<80;i++)

{

TxBuffer1[i]= buf[i];

}

DMA_send(80);

num=0;

}

}

5.測(cè)試結(jié)果如下,在2.5M波特率的情況下保持?jǐn)?shù)據(jù)完整。

87df6632-39f0-11ed-b180-dac502259ad0.png

寫(xiě)在最后

這次主要討論了一種高負(fù)載情況下如何緩解CPU壓力的方法,所言所寫(xiě)不盡完善,例如不定數(shù)據(jù)接收,就可以通過(guò)DMA_GetCurrDataCounter(DMA_CH2);函數(shù)進(jìn)行傳輸數(shù)據(jù)的統(tǒng)計(jì)計(jì)算,這點(diǎn)大家可以自由發(fā)揮,現(xiàn)實(shí)可能遇到的問(wèn)題是多種多樣的,主要在于關(guān)鍵能力的拓展。更多的還需要根據(jù)實(shí)際情況靈活配置。

閱讀原文:https://bbs.21ic.com/icview-3209220-1-1.html

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 通信
    +關(guān)注

    關(guān)注

    18

    文章

    5880

    瀏覽量

    135321
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    串口通信的基本概念

    串口通信(Serial Communications)的基本概念可以歸納為以下幾個(gè)方面:
    的頭像 發(fā)表于 06-12 09:28 ?384次閱讀
    <b class='flag-5'>串口</b><b class='flag-5'>通信</b>的基本概念

    什么是串口通信?它有哪些特點(diǎn)和應(yīng)用?

    在現(xiàn)代電子通信和計(jì)算機(jī)領(lǐng)域中,串口通信(Serial Communications)扮演著至關(guān)重要的角色。它是一種按位(bit)發(fā)送和接收字節(jié)的通信方式,能夠?qū)崿F(xiàn)數(shù)據(jù)的遠(yuǎn)距離傳輸和高效
    的頭像 發(fā)表于 05-23 16:23 ?1405次閱讀

    串口通信如何控制步進(jìn)電機(jī)轉(zhuǎn)動(dòng)?

    在自動(dòng)化控制系統(tǒng)中,步進(jìn)電機(jī)的控制是一項(xiàng)重要的技術(shù)任務(wù)。通過(guò)串口通信控制步進(jìn)電機(jī)轉(zhuǎn)動(dòng),可以實(shí)現(xiàn)遠(yuǎn)程控制和自動(dòng)化操作,提高生產(chǎn)效率和降低人工成本。本文將詳細(xì)介紹串口通信控制步進(jìn)電機(jī)轉(zhuǎn)動(dòng)的
    的頭像 發(fā)表于 04-19 16:23 ?1364次閱讀

    VC++串口通信詳解

    電子發(fā)燒友網(wǎng)站提供《VC++串口通信詳解.doc》資料免費(fèi)下載
    發(fā)表于 03-24 09:36 ?0次下載

    UART串口通信協(xié)議是什么?

    UART (Universal Asynchronous Receiver/Transmitter) 是一種通信接口協(xié)議,用于實(shí)現(xiàn)串口通信。它是一種簡(jiǎn)單的、可靠的、廣泛應(yīng)用的串口
    的頭像 發(fā)表于 03-19 17:26 ?960次閱讀

    QT串口通信的簡(jiǎn)單使用

    QT串口通信是上位機(jī)和下位機(jī)通信常用的通信方式, 也是學(xué)習(xí)QT必須學(xué)會(huì)的基礎(chǔ)知識(shí), 這篇就簡(jiǎn)單介紹一下QT串口
    的頭像 發(fā)表于 01-15 09:27 ?1419次閱讀
    QT<b class='flag-5'>串口</b><b class='flag-5'>通信</b>的簡(jiǎn)單使用

    單片機(jī)串口通信的接收與發(fā)送程序

    單片機(jī)串口通信的接收與發(fā)送程序 一、引言 單片機(jī)串口通信是一種常見(jiàn)的通信方式,廣泛應(yīng)用于各種嵌入式系統(tǒng)和工業(yè)控制領(lǐng)域。通過(guò)
    的頭像 發(fā)表于 12-19 13:57 ?4419次閱讀

    用proteus和keil實(shí)現(xiàn)串口通信仿真

    前面一課講述了串行口通信的技術(shù)原理,本課通過(guò)安裝虛擬串口,用proteus和keil實(shí)現(xiàn)串口通信仿真。
    的頭像 發(fā)表于 11-27 16:42 ?4515次閱讀
    用proteus和keil實(shí)現(xiàn)<b class='flag-5'>串口</b><b class='flag-5'>通信</b>仿真

    智能車ROS與STM32串口通信代碼

    這里以一個(gè)智能車代碼工程為例,抽取串口通信部分代碼 在頭文件中,進(jìn)行串口頭文件的包含 # include 在類的定義中,什么一個(gè) serial 類的實(shí)例 serial::Serial
    的頭像 發(fā)表于 11-26 17:47 ?1028次閱讀

    ROS與STM32串口通信代碼

    這里以一個(gè)智能車代碼工程為例,抽取串口通信部分代碼 在頭文件中,進(jìn)行串口頭文件的包含 # include 在類的定義中,什么一個(gè) serial 類的實(shí)例 serial::Serial
    的頭像 發(fā)表于 11-17 18:10 ?856次閱讀

    N32G435CBL7 usb不能跟上位機(jī)通信問(wèn)題

    N32G435CBL7 無(wú)外部晶振,usb不能跟上位機(jī)通信這個(gè)問(wèn)題有沒(méi)有人遇到過(guò),怎么解決這個(gè)問(wèn)題
    發(fā)表于 11-13 09:04

    STM32里的串口通信

    STM32里的串口通信 在STM32里,串口通信是USART,STM32可以通過(guò)串口和其他設(shè)備進(jìn)行傳輸并行數(shù)據(jù),是全雙工,異步時(shí)鐘控制,設(shè)備
    的頭像 發(fā)表于 11-10 15:58 ?2601次閱讀
    STM32里的<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    licheepi 4a串口通信(usb串口)

    licheepi 4a串口通信(usb串口)
    的頭像 發(fā)表于 11-08 09:09 ?481次閱讀
    licheepi 4a<b class='flag-5'>串口</b><b class='flag-5'>通信</b>(usb<b class='flag-5'>串口</b>)

    基于N32G435負(fù)載串口通信

    基于N32G435負(fù)載串口通信
    的頭像 發(fā)表于 11-07 17:19 ?1026次閱讀
    基于<b class='flag-5'>N32G435</b>的<b class='flag-5'>高</b><b class='flag-5'>負(fù)載</b><b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    如何提升AT32F435/437性能

    AT32F435/437 Performance Improvement描述了如何通過(guò)軟件方法改善AT32F435_437的運(yùn)行效能。
    發(fā)表于 10-25 07:37