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 67a2774..ef7b7ea 100755 Binary files a/F1:F103/FX3U/fx3u.bin and b/F1:F103/FX3U/fx3u.bin differ 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"