最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

基于STM32F4的多摩川協(xié)議通訊實現(xiàn)詳解

2023-09-21 09:45 作者:電控小子  | 我要投稿

1、介紹

? ? ?編碼器,我們都知道在伺服控制中,為了獲取更高的位置精度,完成更精細(xì)的絕對定位,通常會采用絕對式光電編碼器作為位置反饋傳感器,其常見的兩種主要是17位與23位,編碼器廠商為了增強(qiáng)信息傳輸可靠性,編碼信息一般會采用串行方式輸出,通過特定的通訊協(xié)議控制。這里我們主要介紹一下17位絕對式光電編碼器。

2、編碼器

2.1、接口定義

說明:實際應(yīng)用過程中,如果沒有多圈值記錄需求,可以不接電池,但如果需要長時間保留多圈值數(shù)據(jù),比如多軸機(jī)器人的原點(diǎn)數(shù)據(jù),這種情況則需要接入電池。

2.2、電氣參數(shù)

說明:1、輸出信號符合RS485接口,負(fù)載電流Imax:±50mA;

? 2、消耗電流:≤120mA(無負(fù)載情況);

? 3、絕緣阻抗10MΩ以上(0V與殼之間,DC500V);

2.2、通訊電路

說明:1、IC1為線性差分驅(qū)動器,功能等同于MAX485;

???????????? 2、IC2為線性差分接收器,功能等同于MAX485,推薦使用ADM485;

? 3、匹配電阻:編碼器匹配電阻R2為220Ω,推薦用戶接收端匹配電阻R5≥120Ω;

? 4、上/下拉電阻:編碼器上/下拉電阻R1、R3為4.7KΩ,推薦用戶接收端上/下拉電阻R4、R6不小于1KΩ。

2.3、協(xié)議

根據(jù)編碼器電氣參數(shù)與通訊電路,我們可以確定通訊方式,STM32采用USART模塊,串口波特率設(shè)置2.5Mbps,以下是多摩川協(xié)議時序圖:


說明:1、CF:控制域,用戶發(fā)送命令CF與編碼器返回的CF一致;

? 2、SF:狀態(tài)域,編碼器返回錯誤信息與報警信息;

? 3、DF:數(shù)據(jù)域,編碼器返回數(shù)據(jù);

? 4、CRC:校驗域,CRC多項式:G(X)=??8+1,校驗范圍CF、SF、DF。

2.3.1、控制字CF

說明:1、根據(jù)時序圖可以知道發(fā)送請求只需要發(fā)送CF即可,具體CF值可以根據(jù)上表分析,CF結(jié)構(gòu)主要是start bit(0)+sink code+Data ID code+ID parity+Delimiter(1),這里注意一下開始位(0)與結(jié)束位(1),與串口無校驗發(fā)送里面的開始位與結(jié)束位一樣的嘛,所以我們其實只需要發(fā)送sink code+Data ID code+ID parity就可以了;

? 2、根據(jù)時序圖可以看到sink code 固定為010,剩下的Data ID code+ID parity看自己需求查表對應(yīng)上就行,經(jīng)常用的主要是ID0=0x02與ID3=0x1A,其余我就不說了,貼代碼。

? 3、這里注意一下,編碼器返回的報文CF位必須與發(fā)送CF一致,在處理接收報文時需校驗一下。

/* 宏定義聲明 —————————————————————-*/

#define ? ? ? ? DataId0 ? ? ? ? ? ? 0x02 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*讀取單圈*/

#define ? ? ? ? DataId1 ? ? ? ? ? ? 0x8A ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*讀取圈數(shù)*/

#define ? ? ? ? DataId2 ? ? ? ? ? ? 0x92 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*讀取編碼器編號*/

#define ? ? ? ? DataId3 ? ? ? ? ? ? 0x1A ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*讀取單圈+圈數(shù)*/

#define ? ? ? ? DataId6 ? ? ? ? ? ? 0x32 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*寫EEPROM*/

#define ? ? ? ? DataIdD ? ? ? ? ? ? 0xEA ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*讀EEPEOM*/

#define ? ? ? ? DataId7 ? ? ? ? ? ? 0xBA ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*重置錯誤ERROR*/

#define ? ? ? ? DataId8 ? ? ? ? ? ? 0xC2 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*重置圈數(shù)*/

#define ? ? ? ? DataIdC ? ? ? ? ? ? 0x62 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*重置圈數(shù)與ERROR*/ ?

2.3.2、狀態(tài)字SF

說明:狀態(tài)位SF主要反饋編碼器狀態(tài),包括編碼器是否過熱、電池供電是否正常、數(shù)據(jù)解析是否正確等。

2.3.3、數(shù)據(jù)字DF

根據(jù)發(fā)出的CF不同,編碼器返回的DF也會不同,具體的對應(yīng)關(guān)系如下表:

說明:1、ABS0-ABS2:編碼器單圈值,由于STM32的串口是小端模式,所以實際 編碼器單圈位置值=(ABS2<<16)|(ABS1<<8)|(ABS0<<0);

? 2、ABM0-ABM2:編碼器圈數(shù)值,實際編碼器圈數(shù)值=(ABM2<<16)|(ABM1<<8)|(ABM0<<0)。

說明:ALMC:編碼器錯誤,不同數(shù)值都有其對應(yīng)的故障,對應(yīng)查表即可。

2.4.4、校驗字CRC

說明:這里注意一下,我們采用的是小端異或的計算方式,根據(jù)多項式 G(X)=??8+1 其對應(yīng)的二進(jìn)制數(shù)為0x101,其Ploy值為0x01,LSB First=0x80,我們需要將CF+SF+DF以字節(jié)形式分別于LSB First進(jìn)行亦或處理,最后結(jié)果為CRC8校驗結(jié)果,具體實現(xiàn)過程見代碼。


/******************************************************************************

? * 函數(shù)功能: ? CRC8校驗函數(shù)

? * 輸入?yún)?shù): ? *message:接收的數(shù)據(jù)指針

? ? ? ? ? ? ? ? len:數(shù)據(jù)長度

? * 返 回 值: ? ? ?CRC8校驗值

? ? * 說 ? ?明: 多項式:G(X)=X^8+1 LSB first ?Poly: 0000 0001

? ? ? ? ? ? ? ? ? ? ? ? LSB first ?: 1000 0000 =0X80

*****************************************************************************/ ?

uint8_t APP_Math_CRC8_ChkValue(uint8_t *message, uint8_t len)

{

? ? uint8_t crc_val;

? ? uint8_t i;

? ? crc_val = 0;

? ? while(len–)

? ? {

? ? ? ? crc_val ^= *message++;

? ? ? ? for(i = 0;i < 8;i++)

? ? ? ? {

? ? ? ? ? ? if(crc_val & 0x01)

? ? ? ? ? ? ? ? crc_val = (crc_val >> 1) ^ 0X80;

? ? ? ? ? ? else

? ? ? ? ? ? ? ? crc_val >>= 1;

? ? ? ? }

? ? }

? ? return crc_val;

}

3、單片機(jī)

3.1、單片機(jī)

當(dāng)時項目為了上手快一點(diǎn),又怕串口波特率不夠,所以就選了個STM32F405RGT6,168MHz主頻綽綽有余,現(xiàn)在想想有點(diǎn)殺雞用牛刀了,這里主要提一下接下來要用到的串口與DMA。STM32F405有16數(shù)據(jù)流DMA,支持FIFOs模式與觸發(fā)模式,4 個 USART/2 個 UART(速率可達(dá)10.5 Mbit/s,支持ISO7816接口)。

3.2、串口+DMA

?串口(UART)是一種低速的串行異步通信,通常使用的波特率小于或等于115200bps,對于這種數(shù)據(jù)量不大的通信場景,一般沒必要使用DMA,或者說使用DMA并未能充分發(fā)揮出DMA的作用。當(dāng)面對數(shù)量大或者高波特率時,就必須使用DMA以釋放CPU資源,因為高波特率可能帶來CPU資源過度浪費(fèi)的問題。這里編碼器電氣參數(shù)要求通訊速率≥2.5MHz,我們一般選擇將串口波特率設(shè)置為2.5MHz,同時為了不占用太多CPU資源,CF發(fā)送與編碼器數(shù)據(jù)接收都會采用DMA,具體寄存器設(shè)置如下:


/******************************************************************************

? * 函數(shù)功能: ? USART2+DMA初始化函數(shù)

? * 輸入?yún)?shù): ? 無

? * 返 回 值: ? ? ?無

? ? * 說 ? ?明: ? 外部調(diào)用-多摩川編碼器1

*****************************************************************************/ ?

void BSP_Encoder1_InitConfig(void)

{

? ? GPIO_InitTypeDef ? ?GPIO_InitStructure;

? ? USART_InitTypeDef USART_InitStructure;

? ? DMA_InitTypeDef ? ? DMA_InitStructure;

? ? NVIC_InitTypeDef ? ?NVIC_InitStructure;

? ?

? ? RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

? ? RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

? ? GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*UART2-TX*/

? ? GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*UART2-RX*/

? ? GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

? ? GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

? ? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*UART2-TX*/

? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

? ? GPIO_Init(GPIOA, &GPIO_InitStructure);

? ? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

? ? GPIO_Init(GPIOA, &GPIO_InitStructure); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*UART2-RX*/

? ?

? ? RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); ?

? ? GPIO_InitStructure.GPIO_Pin ? = GPIO_Pin_15; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*DIR1-PC15*/

? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; ?

? ? GPIO_InitStructure.GPIO_Mode ?= GPIO_Mode_OUT;

? ? GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

? ? GPIO_InitStructure.GPIO_PuPd ?= GPIO_PuPd_UP; ?

? ? GPIO_Init(GPIOC, ? ?&GPIO_InitStructure); ?

? ? GPIO_ResetBits(GPIOC,GPIO_Pin_15); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*初始化關(guān)閉通信*/

? ?

? ? RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*串口發(fā)DMA配置*/

? ? NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*搶占優(yōu)先級0-3,響應(yīng)優(yōu)先級0-3*/

? ? NVIC_InitStructure.NVIC_IRQChannel=DMA1_Stream6_IRQn; ? ? ? ? ? ? ?

? ? NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*搶占優(yōu)先級1*/

? ? NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

? ? NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

? ? NVIC_Init(&NVIC_InitStructure); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*DMA發(fā)送中斷*/

? ? DMA_DeInit(DMA1_Stream6); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*DMA通道配置*/

? ? while(DMA_GetCmdStatus(DMA1_Stream6)!=DISABLE){} ? ?

? ? DMA_InitStructure.DMA_Channel = DMA_Channel_4;

? ? DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR); ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*外設(shè)地址*/

? ? DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Ed_Tx_Buf1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*內(nèi)存地址*/

? ? DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*dma傳輸方向*/

? ? DMA_InitStructure.DMA_BufferSize = USART_MAX_TX_LEN; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*設(shè)置DMA在傳輸時緩沖區(qū)的長度*/

? ? DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*設(shè)置DMA的外設(shè)遞增模式,一個外設(shè)*/

? ? DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*設(shè)置DMA的內(nèi)存遞增模式*/

? ? DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; ? ? ? ? ? ? ? ? ? ? ? ? /*外設(shè)數(shù)據(jù)字長*/

? ? DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte; ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*內(nèi)存數(shù)據(jù)字長*/

? ? DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*設(shè)置DMA的傳輸模式*/

? ? DMA_InitStructure.DMA_Priority = DMA_Priority_High; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*設(shè)置DMA的優(yōu)先級別*/

? ? DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*指定如果FIFO模式或直接模式將用于指定的流:不使能FIFO模式*/ ?

? ? DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*指定了FIFO閾值水平*/ ?

? ? DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*指定的Burst轉(zhuǎn)移配置內(nèi)存?zhèn)鬏?/

? ? DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*指定的Burst轉(zhuǎn)移配置外圍轉(zhuǎn)移*/

? ? DMA_Init(DMA1_Stream6, &DMA_InitStructure); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*配置DMA1的通道*/ ? ?

? ? DMA_ITConfig(DMA1_Stream6,DMA_IT_TC,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*使能中斷*/

? ?

? ? DMA_DeInit(DMA1_Stream5); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*串口接收DMA配置*/

? ? while(DMA_GetCmdStatus(DMA1_Stream5)!=DISABLE){} ? ? ? ?

? ? DMA_InitStructure.DMA_Channel = DMA_Channel_4;

? ? DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR); ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*外設(shè)地址*/

? ? DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Ed_Rx_Buf1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*內(nèi)存地址*/

? ? DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*DMA傳輸方向*/

? ? DMA_InitStructure.DMA_BufferSize = USART_MAX_RX_LEN; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*設(shè)置DMA在傳輸時緩沖區(qū)的長度*/

? ? DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*設(shè)置DMA的外設(shè)遞增模式,一個外設(shè)*/

? ? DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*設(shè)置DMA的內(nèi)存遞增模式*/

? ? DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; ? ? ? ? ? ? ? ? ? ? ? ? /*外設(shè)數(shù)據(jù)字長*/

? ? DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*內(nèi)存數(shù)據(jù)字長*/

? ? DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*設(shè)置DMA的傳輸模式*/

? ? DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*設(shè)置DMA的優(yōu)先級別*/

? ? DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*指定如果FIFO模式或直接模式將用于指定的流 : 不使能FIFO模式*/ ? ?

? ? DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*指定了FIFO閾值水平*/ ? ?

? ? DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*指定的Burst轉(zhuǎn)移配置內(nèi)存?zhèn)鬏?/ ? ? ?

? ? DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*指定的Burst轉(zhuǎn)移配置外圍轉(zhuǎn)移*/

? ? DMA_Init(DMA1_Stream5, &DMA_InitStructure); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*配置DMA1的通道*/ ?

? ? DMA_Cmd(DMA1_Stream5,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*使能通道*/

? ? USART_InitStructure.USART_BaudRate = ENCODER1_BAUDRATE; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*配置8 1 0*/

? ? USART_InitStructure.USART_WordLength = USART_WordLength_8b;

? ? USART_InitStructure.USART_StopBits = USART_StopBits_1;

? ? USART_InitStructure.USART_Parity = USART_Parity_No ;

? ? USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

? ? USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

? ? USART_Init(USART2, &USART_InitStructure);

? ?

? ? NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*通道設(shè)置為串口中斷*/ ?

? ? NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*中斷占先等級*/

? ? NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*中斷響應(yīng)優(yōu)先級*/

? ? NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*打開中斷*/ ?

? ? NVIC_Init(&NVIC_InitStructure); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*配置中斷*/ ?

? ?

? ? USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*采用DMA方式發(fā)送*/

? ? USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*采用DMA方式接收*/

? ? USART_ITConfig(USART2,USART_IT_TC,DISABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*中斷配置*/

? ? USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);

? ? USART_ITConfig(USART2,USART_IT_TXE,DISABLE);

? ? USART_ITConfig(USART2,USART_IT_IDLE,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*開啟USART2空中斷*/

? ? USART_Cmd(USART2, ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*啟動串口*/ ?

}

另附DMA1、DMA2每個控制的8個數(shù)據(jù)流和其對應(yīng)的通道:

?

4、代碼實現(xiàn)

至此串口DMA初始化完成,接下來就是具體的發(fā)送與接收,發(fā)送直接采用DMA傳輸完成中斷,接收稍微需要點(diǎn)處理,因為我們接收的是不定長度的數(shù)據(jù),所以需要通過串口的空閑中斷來判斷數(shù)據(jù)接收結(jié)束,數(shù)據(jù)接收完畢之后需要對CF、CRC進(jìn)行校驗,校驗通過才可認(rèn)為DF數(shù)據(jù)可用,具體代碼實現(xiàn)如下:


/******************************************************************************

? * 函數(shù)功能: ? ? ? USART2中斷處理函數(shù)

? * 輸入?yún)?shù): ? 無

? * 返 回 值: ? ? ?無

? ? * 說 ? ?明: ? 外部調(diào)用-多摩川編碼器1

*****************************************************************************/ ?

void USART2_IRQHandler(void) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*串口2中斷服務(wù)程序*/

{

? ? if(USART_GetITStatus(USART2,USART_IT_IDLE)!=RESET) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*空閑中斷觸發(fā)*/

? ? {

? ? ? ? DMA_Cmd(DMA1_Stream5, DISABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 暫時關(guān)閉DMA數(shù)據(jù)尚未處理 */

? ? ? ? ED_RX_LEN1 = USART_MAX_RX_LEN – DMA_GetCurrDataCounter(DMA1_Stream5); ? ? ? ? ? ? ? ? ? ? ? /* 獲取接收到的數(shù)據(jù)長度*/

? ? ? ? BSP_Encoder1_DMA_DataProcess(Ed_Tx_Buf1,Ed_Rx_Buf1,ED_RX_LEN1); ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 報文數(shù)據(jù)處理*/

? ? ? ? DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 清DMA標(biāo)志位 */

? ? ? ? DMA_SetCurrDataCounter(DMA1_Stream5,USART_MAX_RX_LEN); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 重新賦值計數(shù)值,必須大于等于最大可能接收到的數(shù)據(jù)幀數(shù)目 */

? ? ? ? DMA_Cmd(DMA1_Stream5, ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*打開DMA*/

? ? ? ? USART_ReceiveData(USART2); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*清除空閑中斷標(biāo)志位,接收函數(shù)有清標(biāo)志位的作用*/

? ? ? ? Ed_Flag_Rx_Busy1 = 1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*狀態(tài)位更新-USART2接收完成*/ ? ? ? ? ? ?

? ? }

? ? if(USART_GetFlagStatus(USART2,USART_IT_TXE)==RESET) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*串口發(fā)送完成*/

? ? {

? ? ? ? Ed_Flag_Tx_Busy1=0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? USART_ITConfig(USART2,USART_IT_TC,DISABLE);

? ? }

}

/******************************************************************************

? ? * 函數(shù)功能: ? ? DMA1_Stream6中斷處理函數(shù)

? ? * 輸入?yún)?shù): ? ? 無

? ? * 返 回 值: ? ?無

? ? * 說 ? ?明: ? 外部調(diào)用-多摩川編碼器1

*****************************************************************************/ ?

void DMA1_Stream6_IRQHandler(void)

{

? ? if(DMA_GetFlagStatus(DMA1_Stream6,DMA_FLAG_TCIF6)!=RESET) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*等待DMA1_Steam6傳輸完成*/

? ? {

? ? ? ? DMA_ClearFlag(DMA1_Stream6,DMA_FLAG_TCIF6); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*清除DMA1_Steam6傳輸完成標(biāo)志*/

? ? ? ? DMA_Cmd(DMA1_Stream6,DISABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*關(guān)閉使能*/

? ? ? ? USART_ITConfig(USART2,USART_IT_TC,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*打開串口發(fā)送完成中斷*/

? ? }

}

/******************************************************************************

? ? * 函數(shù)功能: ? ? DMA_USART2發(fā)送函數(shù)

? ? * 輸入?yún)?shù): ? ? *data:發(fā)送的數(shù)據(jù)指針

? ? ? ? ? ? ? ? ? ? size:數(shù)據(jù)長度

? ? * 返 回 值: ? ?無

? ? * 說 ? ?明: ? 外部調(diào)用-多摩川編碼器1

*****************************************************************************/ ?

void BSP_Encoder1_DMA_SendBuffer(u8 *data,u16 size) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

{

? ? Ed_Flag_Tx_Busy1=1; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*狀態(tài)位更新-USART2發(fā)送中*/

? ? memcpy(Ed_Tx_Buf1,data,size); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*復(fù)制數(shù)據(jù)到DMA發(fā)送緩存區(qū)*/

? ? while (DMA_GetCmdStatus(DMA1_Stream6) != DISABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*確保DMA可以被設(shè)置*/

? ? DMA_SetCurrDataCounter(DMA1_Stream6,size); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*設(shè)置數(shù)據(jù)傳輸長度*/

? ? DMA_Cmd(DMA1_Stream6,ENABLE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*打開DMA數(shù)據(jù)流,開始發(fā)送*/

}

/******************************************************************************

? ? * 函數(shù)功能: ? ? DMA_USART2數(shù)據(jù)處理函數(shù)

? ? * 輸入?yún)?shù): ? ? *data:接收的數(shù)據(jù)指針

? ? ? ? ? ? ? ? ? ? size:數(shù)據(jù)長度

? ? * 返 回 值: ? ?無

? ? * 說 ? ?明: ? 外部調(diào)用-多摩川編碼器2

*****************************************************************************/ ?

void ? ?BSP_Encoder1_DMA_DataProcess(u8 *txdata,u8 *rxdata,u16 size)

{

? ? uint8_t ? ? crc=0;

? ? uint8_t ? ? buf[USART_MAX_RX_LEN]={0}; ?

? ? for(int i=0;i<size;i++)

? ? ? ? buf[i]=*rxdata++;

? ? if(buf[0]==*txdata)

? ? {

? ? ? ? crc=APP_Math_CRC8_ChkValue(buf,size-1);

? ? ? ? if(crc==buf[size-1])

? ? ? ? {

? ? ? ? ? ? Encoder1_CodeValue=buf[4]<<16|buf[3]<<8|buf[2];

? ? ? ? }

? ? ? ? else

? ? ? ? {

? ? ? ? ? ? Encoder_ReadFaultNum++;

? ? ? ? ? ? if(Encoder_ReadFaultNum>ED_READ_FAULT_MAXNUM)

? ? ? ? ? ? ? ? Encoder_ReadStatus=1; ? ? ? ? ?

? ? ? ? }

? ? }

? ? else

? ? {

? ? ? ? ? ? Encoder_ReadFaultNum++;

? ? ? ? ? ? if(Encoder_ReadFaultNum>ED_READ_FAULT_MAXNUM)

? ? ? ? ? ? ? ? Encoder_ReadStatus=1;

? ? }

}


基于STM32F4的多摩川協(xié)議通訊實現(xiàn)詳解的評論 (共 條)

分享到微博請遵守國家法律
巴彦县| 中江县| 灵宝市| 察雅县| 晋州市| 南宫市| 饶阳县| 德兴市| 图木舒克市| 板桥市| 南乐县| 郧西县| 瑞昌市| 施甸县| 潞城市| 南澳县| 延庆县| 中西区| 旌德县| 图木舒克市| 泗阳县| 五河县| 南澳县| 孝感市| 五原县| 都兰县| 临澧县| 井陉县| 林口县| 渝北区| 汉阴县| 济南市| 兰州市| 绥滨县| 阳城县| 长兴县| 北安市| 林芝县| 大竹县| 江陵县| 比如县|