From 03772fce3a990196fd0b3612722f36dd590142c8 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 24 Sep 2024 18:13:23 +0300 Subject: [PATCH] add modbus RTU --- F1:F103/FX3U/can.c | 1 + F1:F103/FX3U/canproto.c | 1 + F1:F103/FX3U/fx3u.bin | Bin 14576 -> 15008 bytes F1:F103/FX3U/hardware.c | 39 +++++++++++++++++------------- F1:F103/FX3U/hardware.h | 4 ++++ F1:F103/FX3U/modbusproto.c | 10 ++++++++ F1:F103/FX3U/modbusrtu.c | 48 +++++++++++++++++++++++++++++++------ F1:F103/FX3U/usart.c | 2 +- F1:F103/FX3U/version.inc | 4 ++-- 9 files changed, 83 insertions(+), 26 deletions(-) diff --git a/F1:F103/FX3U/can.c b/F1:F103/FX3U/can.c index 0b59e32..b4374a6 100644 --- a/F1:F103/FX3U/can.c +++ b/F1:F103/FX3U/can.c @@ -122,6 +122,7 @@ void CAN_setup(uint32_t speed){ uint32_t tmout = 16000000; // Configure GPIO: PD0 - CAN_Rx, PD1 - CAN_Tx AFIO->MAPR |= AFIO_MAPR_CAN_REMAP_REMAP3; + AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE; // I don't know why, but without this string JTAG works (despite on turning it off in hardware.c)! GPIOD->CRL = (GPIOD->CRL & ~(CRL(0,0xf)|CRL(1,0xf))) | CRL(0, CNF_FLINPUT | MODE_INPUT) | CRL(1, CNF_AFPP | MODE_NORMAL); /* Enable the peripheral clock CAN */ diff --git a/F1:F103/FX3U/canproto.c b/F1:F103/FX3U/canproto.c index e0e6c16..4b7b37c 100644 --- a/F1:F103/FX3U/canproto.c +++ b/F1:F103/FX3U/canproto.c @@ -163,6 +163,7 @@ static errcodes u32setget(CAN_message *msg){ case CMD_INCHNLS: val = inchannels(); ptr = &val; break; case CMD_OUTCHNLS: val = outchannels(); ptr = &val; break; case CMD_MODBUSID: ptr = &the_conf.modbusID; break; + case CMD_MODBUSSPEED: ptr = &the_conf.modbusspeed; break; default: break; } if(!ptr) return ERR_CANTRUN; // unknown error diff --git a/F1:F103/FX3U/fx3u.bin b/F1:F103/FX3U/fx3u.bin index 67a27748fd45dbd8ea58a1ce31216d16352d235b..ef7b7ea1dd613c5bd2cb4878d92fbf430123f641 100755 GIT binary patch delta 5257 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 delta 4748 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 B70Uns diff --git a/F1:F103/FX3U/hardware.c b/F1:F103/FX3U/hardware.c index 5e3f893..cec837c 100644 --- a/F1:F103/FX3U/hardware.c +++ b/F1:F103/FX3U/hardware.c @@ -69,7 +69,9 @@ Xn - inputs, Yn - outputs, ADCn - ADC inputs | 67 | PA8 | Y2 | PPOUT | | | 68 | PA9 | RS TX | AFPP | | | 69 | PA10 | RS RX | FLIN | | -| 76 | PA14/SWCLK | 485 DE * | (default) | (Not now) RS-485 Data Enable | +| 76 | PA14/SWCLK | 485 DE | PPOUT | RS-485 Data Tx Enable | +| 78 | PC10 | 485 TX | AFPP | RS-485 Tx | +| 79 | PC11 | 485 RX | FLIN | RS-485 Rx | | 81 | PD0 | CAN RX | FLIN | | | 82 | PD1 | CAN TX | AFPP | | | 89 | PB3/JTDO | Y4 | PPOUT | | @@ -82,27 +84,32 @@ void gpio_setup(void){ // PD0 & PD1 (CAN) setup in can.c; PA9 & PA10 (USART) in usart.c RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN; - // Turn off JTAG - AFIO->MAPR = AFIO_MAPR_SWJ_CFG_JTAGDISABLE; - GPIOA->CRL = CRL(0, CNF_PPOUTPUT|MODE_NORMAL) | CRL(1, CNF_ANALOG) | CRL(2, CNF_PPOUTPUT|MODE_NORMAL) | - CRL(3, CNF_ANALOG) | CRL(6, CNF_PPOUTPUT|MODE_NORMAL) | CRL(7, CNF_PPOUTPUT|MODE_NORMAL); - GPIOA->CRH = CRH(8, CNF_PPOUTPUT|MODE_NORMAL); - GPIOB->CRL = CRL(2, CNF_PUDINPUT) | CRL(3, CNF_PPOUTPUT|MODE_NORMAL); - GPIOB->CRH = CRH(10, CNF_PUDINPUT) | CRH(11, CNF_PUDINPUT) | CRH(12, CNF_PUDINPUT) | CRH(13, CNF_PUDINPUT) | - CRH(14, CNF_PUDINPUT) | CRH(15, CNF_PPOUTPUT|MODE_NORMAL); - GPIOC-> CRL = CRL(0, CNF_ANALOG) | CRL(1, CNF_ANALOG) | CRL(4, CNF_ANALOG) | CRL(5, CNF_ANALOG); - GPIOC->CRH = CRH(8, CNF_PPOUTPUT|MODE_NORMAL) | CRH(9, CNF_PPOUTPUT|MODE_NORMAL); - GPIOD->CRL = 0; - GPIOD->CRH = CRH(10, CNF_PPOUTPUT|MODE_NORMAL) | CRH(12, CNF_PPOUTPUT|MODE_NORMAL); - GPIOE->CRL = CRL(7, CNF_PUDINPUT); - GPIOE->CRH = CRH(8, CNF_PUDINPUT) | CRH(9, CNF_PUDINPUT) | CRH(10, CNF_PUDINPUT) | CRH(11, CNF_PUDINPUT) | - CRH(12, CNF_PUDINPUT) | CRH(13, CNF_PUDINPUT) | CRH(14, CNF_PUDINPUT) | CRH(15, CNF_PUDINPUT); + // Turn off JTAG/SWD to use PA14 + AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE; + // be sure that all OK + // __ISB(); + // __DSB(); // pullups & initial values GPIOA->ODR = 0; GPIOB->ODR = (1<<2) | (1<<10) | (1<<11) | (1<<12) | (1<<13) | (1<<14); GPIOC->ODR = 0; GPIOD->ODR = (1<<10); // turn off LED GPIOE->ODR = (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<12) | (1<<13) | (1<<14) | (1<<15); + // configuration + GPIOA->CRL = CRL(0, CNF_PPOUTPUT|MODE_NORMAL) | CRL(1, CNF_ANALOG) | CRL(2, CNF_PPOUTPUT|MODE_NORMAL) | + CRL(3, CNF_ANALOG) | CRL(6, CNF_PPOUTPUT|MODE_NORMAL) | CRL(7, CNF_PPOUTPUT|MODE_NORMAL); + //GPIOA->CRH = CRH(8, CNF_PPOUTPUT|MODE_NORMAL) | CRH(14, CNF_PPOUTPUT|MODE_NORMAL); + GPIOA->CRH = CRH(8, CNF_PPOUTPUT|MODE_NORMAL) | CRH(14, CNF_ODOUTPUT|MODE_NORMAL); + GPIOB->CRL = CRL(2, CNF_PUDINPUT) | CRL(3, CNF_PPOUTPUT|MODE_NORMAL); + GPIOB->CRH = CRH(10, CNF_PUDINPUT) | CRH(11, CNF_PUDINPUT) | CRH(12, CNF_PUDINPUT) | CRH(13, CNF_PUDINPUT) | + CRH(14, CNF_PUDINPUT) | CRH(15, CNF_PPOUTPUT|MODE_NORMAL); + GPIOC->CRL = CRL(0, CNF_ANALOG) | CRL(1, CNF_ANALOG) | CRL(4, CNF_ANALOG) | CRL(5, CNF_ANALOG); + GPIOC->CRH = CRH(8, CNF_PPOUTPUT|MODE_NORMAL) | CRH(9, CNF_PPOUTPUT|MODE_NORMAL); + GPIOD->CRL = 0; + GPIOD->CRH = CRH(10, CNF_PPOUTPUT|MODE_NORMAL) | CRH(12, CNF_PPOUTPUT|MODE_NORMAL); + GPIOE->CRL = CRL(7, CNF_PUDINPUT); + GPIOE->CRH = CRH(8, CNF_PUDINPUT) | CRH(9, CNF_PUDINPUT) | CRH(10, CNF_PUDINPUT) | CRH(11, CNF_PUDINPUT) | + CRH(12, CNF_PUDINPUT) | CRH(13, CNF_PUDINPUT) | CRH(14, CNF_PUDINPUT) | CRH(15, CNF_PUDINPUT); } diff --git a/F1:F103/FX3U/hardware.h b/F1:F103/FX3U/hardware.h index dd43573..5155394 100644 --- a/F1:F103/FX3U/hardware.h +++ b/F1:F103/FX3U/hardware.h @@ -41,6 +41,10 @@ #define LEDPORT GPIOD #define LEDPIN (1<<10) +// RS-485 receive/transmit (PA14: 0-Rx, 1-Tx) +#define RS485_TX() pin_set(GPIOA, (1<<14)) +#define RS485_RX() pin_clear(GPIOA, (1<<14)) + extern volatile uint32_t Tms; void gpio_setup(void); diff --git a/F1:F103/FX3U/modbusproto.c b/F1:F103/FX3U/modbusproto.c index cacab57..322ed69 100644 --- a/F1:F103/FX3U/modbusproto.c +++ b/F1:F103/FX3U/modbusproto.c @@ -26,6 +26,7 @@ // send error static void senderr(modbus_request *r, uint8_t exception){ + if(r->ID == 0) return; // don't answer to broadcasting packets modbus_response resp = {.ID = the_conf.modbusID, .Fcode = r->Fcode | MODBUS_RESPONSE_ERRMARK, .datalen = exception}; modbus_send_response(&resp); } @@ -132,6 +133,7 @@ TRUE_INLINE void writecoil(modbus_request *r){ senderr(r, ME_ILLEGAL_ADDRESS); return; } + if(r->ID == 0) return; modbus_send_request(r); // answer with same data } @@ -147,6 +149,7 @@ TRUE_INLINE void writereg(modbus_request *r){ senderr(r, ME_ILLEGAL_ADDRESS); return; } + if(r->ID == 0) return; modbus_send_request(r); } @@ -171,6 +174,7 @@ TRUE_INLINE void writecoils(modbus_request *r){ senderr(r, ME_NACK); return; } + if(r->ID == 0) return; r->datalen = 0; modbus_send_request(r); } @@ -190,6 +194,7 @@ TRUE_INLINE void writeregs(modbus_request *r){ senderr(r, ME_ILLEGAL_ADDRESS); return; } + if(r->ID == 0) return; r->datalen = 0; modbus_send_request(r); } @@ -199,17 +204,22 @@ TRUE_INLINE void writeregs(modbus_request *r){ // Understand only requests with codes <= 6 void parse_modbus_request(modbus_request *r){ if(!r) return; + int bcast = (r->ID == 0) ? 1 : 0; switch(r->Fcode){ case MC_READ_COIL: + if(bcast) break; // block broadcast reading requests readcoil(r); break; case MC_READ_DISCRETE: + if(bcast) break; readdiscr(r); break; case MC_READ_HOLDING_REG: + if(bcast) break; readreg(r); break; case MC_READ_INPUT_REG: + if(bcast) break; readadc(r); break; case MC_WRITE_COIL: diff --git a/F1:F103/FX3U/modbusrtu.c b/F1:F103/FX3U/modbusrtu.c index a207571..b3fef10 100644 --- a/F1:F103/FX3U/modbusrtu.c +++ b/F1:F103/FX3U/modbusrtu.c @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include "hardware.h" #include "modbusrtu.h" #include "flash.h" #include "strfunc.h" @@ -27,6 +28,20 @@ #include #include // memcpy +/* +static void us(){ + usart_send("MAPR="); printuhex(AFIO->MAPR); + usart_send("\nACRH="); printuhex(GPIOA->CRH); + usart_send("\nODR"); printuhex(GPIOA->ODR); + usart_send("\nIDR"); printuhex(GPIOA->IDR); + AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE; + newline(); +}*/ + +// switch to Rx/Tx: +#define _485_Rx() do{LED(1); RS485_RX(); /*UART4->CR1 = (UART4->CR1 & ~USART_CR1_TE) | USART_CR1_RE;*/}while(0) +#define _485_Tx() do{LED(0); RS485_TX(); /*UART4->CR1 = (UART4->CR1 & ~USART_CR1_RE) | USART_CR1_TE;*/}while(0) + static volatile int modbus_txrdy = 1; static volatile int idatalen[2] = {0,0}; // received data line length (including '\n') @@ -53,6 +68,9 @@ static uint16_t getCRC(uint8_t *data, int l){ }else crc >>= 1; } } +#ifdef EBUG + DBG("Calc CRC: "); printuhex(crc); newline(); +#endif // CRC have swapped bytes, so we can just send it as *((uint16_t*)&data[x]) = CRC return crc; } @@ -87,6 +105,7 @@ static int senddata(int l){ IWDG->KR = IWDG_REFRESH; if(--tmout == 0) return 0; }; // wait for previos buffer transmission + _485_Tx(); modbus_txrdy = 0; DMA2_Channel5->CCR &= ~DMA_CCR_EN; DMA2_Channel5->CMAR = (uint32_t) tbuf[tbufno]; // mem @@ -121,6 +140,7 @@ int modbus_send_request(modbus_request *r){ memcpy(curbuf, r->data, r->datalen); n += r->datalen; } + packCRC(tbuf[tbufno], n) = getCRC(tbuf[tbufno], n); return senddata(n); } @@ -161,6 +181,7 @@ int modbus_send_response(modbus_response *r){ if(len > MODBUSBUFSZO - 2) return -1; // too much data memcpy(curbuf, r->data, r->datalen); } + packCRC(tbuf[tbufno], len) = getCRC(tbuf[tbufno], len); return senddata(len); } @@ -187,11 +208,11 @@ int modbus_get_response(modbus_response* r){ // USART4: PC10 - Tx, PC11 - Rx void modbus_setup(uint32_t speed){ uint32_t tmout = 16000000; - // PA9 - Tx, PA10 - Rx + // PC10 - Tx, PC11 - Rx RCC->APB1ENR |= RCC_APB1ENR_UART4EN; RCC->AHBENR |= RCC_AHBENR_DMA2EN; - GPIOA->CRH = (GPIOA->CRH & ~(CRH(9,0xf)|CRH(10,0xf))) | - CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT); + GPIOC->CRH = (GPIOC->CRH & ~(CRH(10,0xf)|CRH(11,0xf))) | + CRH(10, CNF_AFPP|MODE_NORMAL) | CRH(11, CNF_FLINPUT|MODE_INPUT); // UART4 Tx DMA - Channel5 (Rx - channel 3) DMA2_Channel5->CPAR = (uint32_t) &UART4->DR; // periph DMA2_Channel5->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq @@ -202,15 +223,20 @@ void modbus_setup(uint32_t speed){ // setup uart4 UART4->BRR = 36000000 / speed; // APB1 is 36MHz UART4->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART - while(!(UART4->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission + while(!(UART4->SR & USART_SR_TC)){ // polling idle frame Transmission + IWDG->KR = IWDG_REFRESH; + if(--tmout == 0) break; + } UART4->SR = 0; // clear flags - UART4->CR1 |= USART_CR1_RXNEIE | USART_CR1_IDLEIE; // allow Rx and IDLE IRQ + UART4->CR1 |= USART_CR1_RXNEIE | USART_CR1_IDLEIE | USART_CR1_TCIE; // allow Rx and IDLE IRQ; TC IRQ for switching to Rx UART4->CR3 = USART_CR3_DMAT; // enable DMA Tx NVIC_EnableIRQ(UART4_IRQn); + _485_Rx(); } void uart4_isr(){ if(UART4->SR & USART_SR_IDLE){ // idle - end of frame +usart_send("485: IDLE\n"); modbus_rdy = 1; dlen = idatalen[rbufno]; recvdata = rbuf[rbufno]; @@ -218,15 +244,22 @@ void uart4_isr(){ rbufno = !rbufno; idatalen[rbufno] = 0; (void) UART4->DR; // clear IDLE flag by reading DR - } - if(UART4->SR & USART_SR_RXNE){ // RX not emty - receive next char + }else if(UART4->SR & USART_SR_RXNE){ // RX not emty - receive next char uint8_t rb = UART4->DR; // clear RXNE flag if(idatalen[rbufno] < MODBUSBUFSZI){ // put next char into buf rbuf[rbufno][idatalen[rbufno]++] = rb; +usart_send("485: "); usart_putchar(rb); newline(); }else{ // buffer overrun bufovr = 1; idatalen[rbufno] = 0; } + }else if(UART4->SR & USART_SR_TC){ + if(modbus_txrdy){ +usart_send("->Rx\n"); + _485_Rx(); + } +usart_send("485: TC\n"); + UART4->SR &= ~USART_SR_TC; } } @@ -236,3 +269,4 @@ void dma2_channel4_5_isr(){ modbus_txrdy = 1; } } + diff --git a/F1:F103/FX3U/usart.c b/F1:F103/FX3U/usart.c index 9c70504..ac724e2 100644 --- a/F1:F103/FX3U/usart.c +++ b/F1:F103/FX3U/usart.c @@ -104,7 +104,7 @@ void usart_setup(uint32_t speed){ // PA9 - Tx, PA10 - Rx RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->AHBENR |= RCC_AHBENR_DMA1EN; - GPIOA->CRH = (GPIOA->CRH & ~(CRH(9,0xf)|CRH(10,0xf))) | + GPIOA->CRH = (GPIOA->CRH & ~(CRH(9, 0xf)|CRH(10, 0xf))) | CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT); // USART1 Tx DMA - Channel4 (Rx - channel 5) DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph diff --git a/F1:F103/FX3U/version.inc b/F1:F103/FX3U/version.inc index 91e8782..06d0e3f 100644 --- a/F1:F103/FX3U/version.inc +++ b/F1:F103/FX3U/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "63" -#define BUILD_DATE "2024-09-19" +#define BUILD_NUMBER "85" +#define BUILD_DATE "2024-09-24"