1 | // hardware clock source
|
2 | #define MODBUS_DE_RCC RCC_APB2Periph_GPIOC
|
3 | #define MODBUS_RE_RCC RCC_APB2Periph_GPIOC
|
4 | #define MODBUS_RXTX_RCC RCC_APB2Periph_GPIOB
|
5 | #define MODBUS_UART_PeriphCC RCC_APB1PeriphClockCmd /* USART2 & USART3 @ APB1ENR, USART1 @ APB2ENR */
|
6 | #define MODBUS_UART_RCC RCC_APB1Periph_USART3 /* USART2 & USART3 @ APB1ENR, USART1 @ APB2ENR */
|
7 | #define MODBUS_UART USART3 /* mind DMA request mapping! */
|
8 | #define MODBUS_UART_PIN_REMAP 0
|
9 | #define MODBUS_UART_IRQ USART3_IRQn
|
10 | #define MODBUS_UART_BAUDRATE 38400
|
11 |
|
12 | #if MODBUS_UART_PIN_REMAP
|
13 | #define MODBUS_UART_REMAP_CMD GPIO_PartialRemap_USART3
|
14 | #endif
|
15 |
|
16 | // hardware pins
|
17 | #define MODBUS_RX_PIN GPIO_Pin_11
|
18 | #define MODBUS_RX_PORT GPIOB
|
19 | #define MODBUS_TX_PIN GPIO_Pin_10
|
20 | #define MODBUS_TX_PORT GPIOB
|
21 | #define MODBUS_DE_PIN GPIO_Pin_0
|
22 | #define MODBUS_DE_PORT GPIOC
|
23 | #define MODBUS_RE_PIN GPIO_Pin_1
|
24 | #define MODBUS_RE_PORT GPIOC
|
25 |
|
26 | // DMA options
|
27 | #define MODBUS_RX_DMA_CHANNEL DMA1_Channel3
|
28 | #define MODBUS_TX_DMA_CHANNEL DMA1_Channel2
|
29 | #define MODBUS_RX_DMA_CLRFLAG DMA1_IT_TC3
|
30 | #define MODBUS_TX_DMA_CLRFLAG DMA1_IT_TC2
|
31 | #define MODBUS_RX_DMA_IRQ DMA1_Channel3_IRQn
|
32 | #define MODBUS_TX_DMA_IRQ DMA1_Channel2_IRQn
|
33 | #define MODBUS_USART_DMA_RX_IRQHandler DMA1_Channel3_IRQHandler
|
34 | #define MODBUS_USART_DMA_TX_IRQHandler DMA1_Channel2_IRQHandler
|
35 |
|
36 | // interrupt options
|
37 | #define MODBUS_RX_INTERRUPT_PRIORITY 2
|
38 | #define MODBUS_RX_INTERRUPT_SUBPRIORITY 0
|
39 | #define MODBUS_TX_INTERRUPT_PRIORITY 1
|
40 | #define MODBUS_TX_INTERRUPT_SUBPRIORITY 0
|
41 |
|
42 | /**
|
43 | * @brief Init RS485 hardware interface with DMA
|
44 | * @retval None
|
45 | */
|
46 | void Modbus_Init(void)
|
47 | {
|
48 | GPIO_InitTypeDef GPIO_InitStructure;
|
49 | NVIC_InitTypeDef NVIC_InitStructure;
|
50 | DMA_InitTypeDef DMA_InitStructure;
|
51 | USART_InitTypeDef USART_InitStructure;
|
52 |
|
53 | RCC_APB2PeriphClockCmd(MODBUS_DE_RCC | MODBUS_RE_RCC | MODBUS_RXTX_RCC | RCC_APB2Periph_AFIO, ENABLE);
|
54 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
55 | MODBUS_UART_PeriphCC(MODBUS_UART_RCC, ENABLE);
|
56 |
|
57 | /* DE Pin */
|
58 | GPIO_InitStructure.GPIO_Pin = MODBUS_DE_PIN;
|
59 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
60 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
61 | GPIO_Init(MODBUS_DE_PORT, &GPIO_InitStructure);
|
62 | /* RE Pin */
|
63 | GPIO_InitStructure.GPIO_Pin = MODBUS_RE_PIN;
|
64 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
65 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
66 | GPIO_Init(MODBUS_RE_PORT, &GPIO_InitStructure);
|
67 |
|
68 | #if MODBUS_UART_PIN_REMAP
|
69 | /* Enable the USART Pins Software Remapping */
|
70 | GPIO_PinRemapConfig(MODBUS_UART_REMAP_CMD, ENABLE);
|
71 | #endif
|
72 |
|
73 | /* TX Pin */
|
74 | GPIO_InitStructure.GPIO_Pin = MODBUS_TX_PIN;
|
75 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
76 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
77 | GPIO_Init(MODBUS_TX_PORT, &GPIO_InitStructure);
|
78 | /* RX Pin */
|
79 | GPIO_InitStructure.GPIO_Pin = MODBUS_RX_PIN;
|
80 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
81 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
82 | GPIO_Init(MODBUS_RX_PORT, &GPIO_InitStructure);
|
83 |
|
84 | /* USART */
|
85 | USART_InitStructure.USART_BaudRate = MODBUS_UART_BAUDRATE;
|
86 | USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
87 | USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
88 | USART_InitStructure.USART_Parity = USART_Parity_No;
|
89 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
90 | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
91 |
|
92 | USART_Init(MODBUS_UART, &USART_InitStructure);
|
93 | USART_DMACmd(MODBUS_UART, USART_DMAReq_Tx, ENABLE);
|
94 | USART_DMACmd(MODBUS_UART, USART_DMAReq_Rx, ENABLE);
|
95 | USART_Cmd(MODBUS_UART, ENABLE);
|
96 |
|
97 | /* DMA Channel x (USART RX) */
|
98 | NVIC_InitStructure.NVIC_IRQChannel = MODBUS_RX_DMA_IRQ;
|
99 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
|
100 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
101 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
102 | NVIC_Init(&NVIC_InitStructure);
|
103 |
|
104 | /* DMA Channel x (USART TX)*/
|
105 | NVIC_InitStructure.NVIC_IRQChannel = MODBUS_TX_DMA_IRQ;
|
106 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
107 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
108 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
109 | NVIC_Init(&NVIC_InitStructure);
|
110 |
|
111 | /* DMA Channel for MODBUS_UART TX */
|
112 | DMA_DeInit(MODBUS_TX_DMA_CHANNEL);
|
113 | DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(MODBUS_UART->DR);
|
114 | DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart_transmit_array;
|
115 | DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
116 | DMA_InitStructure.DMA_BufferSize = MODBUS_TRANSMIT_MAX_LENGTH;
|
117 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
118 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
119 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
120 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
121 | DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
122 | DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
123 | DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
124 | DMA_Init(MODBUS_TX_DMA_CHANNEL, &DMA_InitStructure);
|
125 |
|
126 | /* Enable DMA Stream Transfer Complete interrupt */
|
127 | DMA_ITConfig(MODBUS_TX_DMA_CHANNEL, DMA_IT_TC, ENABLE);
|
128 | DMA_Cmd(MODBUS_TX_DMA_CHANNEL, ENABLE);
|
129 |
|
130 | /* DMA Channel for MODBUS_UART RX */
|
131 | DMA_DeInit(MODBUS_RX_DMA_CHANNEL);
|
132 | DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(MODBUS_UART->DR);
|
133 | DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart_receive_array;
|
134 | DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
135 | DMA_InitStructure.DMA_BufferSize = MODBUS_RECEIVE_MAX_LENGTH;
|
136 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
137 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
138 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
139 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
140 | DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
141 | DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
142 | DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
143 | DMA_Init(MODBUS_RX_DMA_CHANNEL, &DMA_InitStructure);
|
144 |
|
145 | /* Enable DMA Stream Transfer Complete interrupt */
|
146 | DMA_ITConfig(MODBUS_RX_DMA_CHANNEL, DMA_IT_TC, ENABLE);
|
147 | DMA_Cmd(MODBUS_RX_DMA_CHANNEL, ENABLE);
|
148 | }
|
149 |
|
150 | /**
|
151 | * @brief basic interrupt handler for USART DMA access
|
152 | * @retval None
|
153 | */
|
154 | void MODBUS_USART_DMA_RX_IRQHandler(void)
|
155 | {
|
156 | /* DMA Transfer Complete interrupt */
|
157 | if (DMA_GetITStatus(MODBUS_RX_DMA_CLRFLAG))
|
158 | {
|
159 | /* Clear DMA Transfer Complete interrupt pending bit */
|
160 | DMA_ClearITPendingBit(MODBUS_RX_DMA_CLRFLAG);
|
161 |
|
162 | /* do something here */
|
163 | bGotDirisResponse = 1;
|
164 | }
|
165 | }
|