簡體   English   中英

STM32F030R8 RS485半雙工不發送

[英]STM32F030R8 RS485 Half Duplex not transmitting

我正在使用STM32F030R8來執行連接到AD3485的RS485通信。 到目前為止,我已經能夠使它正常傳輸,但是當我設置一個中斷處理程序時,似乎中斷是由芯片自身的傳輸觸發的,並停止了所有后續傳輸。

我錯過了在某處設置或清除標志的機會嗎? 我在RS485初始化步驟中錯過了什么嗎? 當傳輸不可避免地觸發中斷請求時,我應該清除標志嗎?

下面,我提供了一個非常精簡但完整的代碼版本,用於傳輸數據,以及捕獲的數據,這些數據我從連接到引腳A9的RS485芯片中看到A10和A12。

這是代碼:

#include "stm32f0xx_conf.h"
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_usart.h>

void SysTick_Handler(void) {

    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    USART_SendData(USART1, 0xAC);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    USART_SendData(USART1, 0x44);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    USART_SendData(USART1, 0x04);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    USART_SendData(USART1, 0x53);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

}

void RS485_Init(){
    GPIO_InitTypeDef GPIO_InitStruct;
    USART_InitTypeDef USART_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_12; // Pins 9 (TX) 10 (RX) 12 (DE) are used
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // the pins are configured as alternate function so the USART peripheral has access to them
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // this defines the IO speed and has nothing to do with the baudrate!
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // this defines the output type as push pull mode (as opposed to open drain)
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // this activates the pullup resistors on the IO pins
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); //
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1);

    USART_InitStruct.USART_BaudRate = 38400 ; // the baudrate is set to the value we passed into this init function
    USART_InitStruct.USART_WordLength = USART_WordLength_8b; // we want the data frame size to be 8 bits (standard)
    USART_InitStruct.USART_StopBits = USART_StopBits_1; // we want 1 stop bit (standard)
    USART_InitStruct.USART_Parity = USART_Parity_No; // we don't want a parity bit (standard)
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // we don't want flow control (standard)
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // we want to enable the transmitter and the receiver
    USART_Init(USART1, &USART_InitStruct);

    USART_HalfDuplexCmd(USART1, ENABLE);
    USART_DECmd(USART1, ENABLE);
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_SetDEAssertionTime(USART1, 0x4E2);
    USART_SetDEDeassertionTime(USART1, 0x4E2);
    USART_DEPolarityConfig(USART1, USART_DEPolarity_High);

    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct); //When I comment this out, I'm able to transmit normally, but without an ISR receiving bytes will be difficult

    USART_Cmd(USART1, ENABLE);

}

//This function handles USART1 global interrupt request.
void USART1_IRQHandler(void)
{

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
        unsigned char USART_Temp_Byte;
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
        USART_Temp_Byte = (unsigned char) USART_ReceiveData(USART1); //receive a char
    }

}

int main(void)
{
    RS485_Init();
    SysTick_Config(SystemCoreClock/1000);
    while(1);
}

這是我啟用中斷時的捕獲(第一次捕獲),與注釋掉NVIC_Init(&NVIC_InitStruct)時的捕獲; 並且沒有ISR觸發:

RS485傳輸問題的邏輯捕獲

這是半/全雙工通信方法的核心原理之一。 RS485是物理層標准,它允許發送器接收自己的數據。 這對於其他標准(軟件層)(例如J1708)很有用。 由於對單個主機和多個從機沒有嚴格的要求,因此每個節點都可以啟動通信。 如果兩個模塊開始同時通話,則需要一種檢測和處理總線爭用/沖突的方案。 使用RS485,您將具有主導(驅動)狀態和隱性(非驅動)狀態。 當發送器開始發送時,您將監視以查看接收到的內容是否與發送的內容匹配,如果不匹配,則很可能是另一台設備嘗試同時發送。 之所以起作用,是因為當您從主導狀態切換為隱性狀態時,總線將返回隱性狀態(無沖突),或者由於另一個接收器握住線路而保持主導狀態(碰撞)。 發生這種情況時,您將停止任何進一步的傳輸,並開始接收或監視總線是否處於空閑狀態。 像J1708這樣的大多數協議,都根據您的地址使用偽隨機數發生器來計算重試延遲,這可以防止相同的兩個模塊不斷沖突。 長話短說:您正在接受所傳送的內容是一件好事。 我建議您使用中斷來比較剛發送的字節和剛接收的字節,如果它們匹配,則發送下一個字節,否則終止並在檢測到下一個空閑狀態后重試。 由於它是相同的中斷例程,因此您需要設置一個標志來指示何時進行傳輸,並控制中斷邏輯以處理比較(Tx部分)或正常接收(Rx部分)

我將這個答案作為對使用該特定芯片的半雙工通信的更新。 通過這種配置,我既可以發送又可以接收。 特別感謝Joe Thomas使我走上正軌。

#include "stm32f0xx_conf.h"
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_usart.h>

void Transmit(void){

    USART_Cmd(USART1, DISABLE);
    USART_DECmd(USART1, ENABLE);
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
    USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
    USART_Cmd(USART1, ENABLE);

    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    USART_SendData(USART1, 0xAC);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    USART_SendData(USART1, 0x44);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    USART_SendData(USART1, 0x04);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    USART_SendData(USART1, 0x53);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    USART_Cmd(USART1, DISABLE);
    USART_DECmd(USART1, DISABLE);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    USART_Cmd(USART1, ENABLE);

}

void SysTick_Handler(void) {

}

void RS485_Init(){

    GPIO_InitTypeDef GPIO_InitStruct;
    USART_InitTypeDef USART_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;



    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1);

    USART_DeInit(USART1);
    USART_StructInit(&USART_InitStruct);
    USART_InitStruct.USART_BaudRate = 38400 ;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS;
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART1, &USART_InitStruct);

    USART_HalfDuplexCmd(USART1, DISABLE);
    USART_DECmd(USART1, DISABLE);
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_SetDEAssertionTime(USART1, 0x4E2);
    USART_SetDEDeassertionTime(USART1, 0x4E2);
    USART_DEPolarityConfig(USART1, USART_DEPolarity_High);



    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    USART_Cmd(USART1, ENABLE);

}

void USART1_IRQHandler(void)
{

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
        unsigned char USART_Temp_Byte;
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
        USART_Temp_Byte = (unsigned char) USART_ReceiveData(USART1); //receive a char
        if(0x53 == USART_Temp_Byte){
            Transmit();
        }
    }

}

int main(void)
{
    RS485_Init();
    SysTick_Config(SystemCoreClock/1000);
    while(1){};
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM