Modbus

huyphuc92

Trứng gà
Chào mọi người.

Mình đang làm modbus trên kit TM4C123, mình dùng modbus Poll để gửi 1 frame xuống kit. Tình hình là gửi một frame 8 byte thì ổn nhưng gửi một frame dài hơn (tối đa 255 byte chẳng hạn) thì phải làm sao nhỉ? Mình thử dùng uDMA mà chưa được. Ai cho mình ý tưởng với.
 

huyphuc92

Trứng gà
Giờ mới mò lại vấn đề này, có tí khởi sắc nhưng gặp thêm vấn đề mới.

Ý tưởng là dùng uDMA, em có đọc được số byte bất kỳ nhưng gặp tình trạng là sau mỗi frame gửi tới VDK, nó tự tăng vị trí lưu trong mảng đích.

Ví dụ: gửi đi '1' thì mảng[0]='1', gửi tiếp theo '2' thì mảng[1]='2', mà em đang muốn mảng[0]='2'. Lý do là sao nhỉ, chưa hiểu???

code em viết ở dưới:
Code:
include này nọ
//===============================================================================================================
uint32_t g_SysClock;
uint8_t Uart_Send_0[255];
uint8_t g_ui8RxBufA[255];
uint8_t g_ui8RxBufB[255];
uint8_t g_ui8TxBuf[255]={49,50,51,52};
int test;
//===============================================================================================================
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];
 
// TODO
void UART0IntHandler(void)
{
 
    uint32_t ui32Status;
 
    ui32Status = UARTIntStatus(UART0_BASE, 1);
 
    UARTIntClear(UART0_BASE, ui32Status);
 
    test++;
}
//===============================================================================================================
 
void uDMAErrorHandler(void)
{
  unsigned long ulStatus;
 
  //
  // Check for uDMA error bit
  //
  ulStatus = uDMAErrorStatusGet();
 
  if(ulStatus)
  {
    uDMAErrorStatusClear();
    //g_uluDMAErrCount++;
  }
}
//===============================================================================================================
void GPIOInit(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_0);
}
//===============================================================================================================
void UartInit(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTConfigSetExpClk(UART0_BASE, g_SysClock, 115200,
                            UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                            UART_CONFIG_PAR_NONE);
    UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    UARTEnable(UART0_BASE);
 
    UARTIntDisable(UART0_BASE , UART_INT_9BIT | UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_RT
                  | UART_INT_TX | UART_INT_RX | UART_INT_DSR | UART_INT_DCD | UART_INT_CTS | UART_INT_RI | UART_INT_DMATX|UART_INT_DMARX);
 
 
    UARTIntClear(UART0_BASE , UART_INT_9BIT | UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_RT
                  | UART_INT_TX | UART_INT_RX | UART_INT_DSR | UART_INT_DCD | UART_INT_CTS | UART_INT_RI | UART_INT_DMATX|UART_INT_DMARX);
    UARTIntEnable(UART0_BASE,UART_INT_RX|UART_INT_RT);
//    UARTIntEnable(UART0_BASE , UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_RX);
    UARTIntUnregister(UART0_BASE);
    UARTIntRegister(UART0_BASE, &UART0IntHandler);
    IntDisable(INT_UART0);
    IntEnable(INT_UART0);
 
    UARTStdioConfig(0,115200,g_SysClock);
 
}
//===============================================================================================================
 
void DMAUart_Init(void)
{
    SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
  SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
  IntDisable(INT_UDMAERR);
  IntEnable(INT_UDMAERR);
  uDMADisable();
  uDMAEnable();
  uDMAControlBaseSet(pui8ControlTable);
 
  UARTDMAEnable(UART0_BASE, UART_DMA_RX);
 
  uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0RX, UDMA_ATTR_ALTSELECT |
                UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY |
                UDMA_ATTR_REQMASK);
 
 
  uDMAChannelControlSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 |
                UDMA_SRC_INC_NONE | UDMA_DST_INC_8|
                UDMA_ARB_4);
 
  uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,
              (void *)(UART0_BASE + UART_O_DR), g_ui8RxBufA, sizeof(g_ui8RxBufA));
 
  uDMAChannelEnable(UDMA_CHANNEL_UART0RX);
  UARTIntEnable(UART0_BASE, UART_INT_DMARX);
 
}
 
//===============================================================================================================
 
 
 
int main(void)
{
    g_SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    GPIOInit();
    UartInit();
    DMAUart_Init();
    UARTprintf("Test Udma\n");
    while(1)
    {
 
    }
}
 

huyphuc92

Trứng gà
Hi cả nhà. Ý tưởng về thư viện modbus trên kit TM4C123G mình đã làm tương đối ổn, coi như là chạy được. Mình share cho mọi người và nhận ý kiến phản hồi. Chỉ cần nạp code vào và dùng phần mềm modbus poll test thử. Có gì thắc mắc mọi người cứ nói nhen.
 

Attachments

huyphuc92

Trứng gà
Hiện còn kẹt chỗ này. Cần một ngắt báo kết thúc frame để ngắt một xung enable TX/RX. Mình có dùng ngắt TX nhưng không ổn lắm, ngắt xuất hiện ở trước byte cuối của frame, kết quả là phải chơi "bùa" một con timer để kiểm tra trạng thái Uart busy. Ai có giải phát không chỉ mình với.
 

huyphuc92

Trứng gà
Thêm link demo thư viện này, một là kết nối WinCC Flexible với kit TM4C1294, và một là kết nối HMI với kit TM4C123G (có cái HMI tốt hơn mà bị kẹt cái RS-485 2 dây với 4 dây nên chưa test được).

Link tải modbus poll để dễ test: https://www.mediafire.com/?3y2f2i2q42gshm2
Chỉ cần cắm cáp nạp và dùng UART0 là test được, file project mình upload trên hình như mình cấu hình UART2 hay UART1 gì đó, sửa lại UART0 là chạy được bằng cổng debug luôn.

Mục đích của thư viện này chỉ giới hạn trong hỗ trợ truyền thông với kit để làm thì nghiệm. Kết nối với PC có thể dùng cổng debug hoặc làm board chuyển TTL -> RS-422/485 cũng được. Nếu dùng board rời phải có một chân Enable TX/RX (là chân DE và RE trên IC). Dùng hàm TxRxEnablePin(uint32_t ui32Port, uint8_t ui8Pins) để đăng ký chân này, chú ý là phải cấu hình GPIO rồi mới dùng hàm này được.

Hiện Timer0 và Timer1 đang dùng nên bạn nào cần timer thì chú ý tránh 2 con timer này ra, hoặc nghĩ cách bỏ 2 con timer này giúp mình, mình tạm thời bó tay :D
 

huunho

Trứng gà
tải xong không mở được, ko biết proj của bạn có thiếu gì ko?
 

huyphuc92

Trứng gà
tải xong không mở được, ko biết proj của bạn có thiếu gì ko?
Bí quá tạo project mới chứ có gì đâu, copy code qua chạy. Mình export project ra y chang chứ có thiếu gì đâu.
 
Top