Rev 8 | Rev 10 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8 | Rev 9 | ||
---|---|---|---|
Line 33... | Line 33... | ||
33 | /* Includes ------------------------------------------------------------------*/ |
33 | /* Includes ------------------------------------------------------------------*/ |
34 | #include "stm32l1xx_hal.h" |
34 | #include "stm32l1xx_hal.h" |
35 | 35 | ||
36 | /* USER CODE BEGIN Includes */ |
36 | /* USER CODE BEGIN Includes */ |
37 | #include "serial.h" |
37 | #include "serial.h" |
- | 38 | #include "plx.h" |
|
- | 39 | #include "misc.h" |
|
38 | /* USER CODE END Includes */ |
40 | /* USER CODE END Includes */ |
39 | 41 | ||
40 | /* Private variables ---------------------------------------------------------*/ |
42 | /* Private variables ---------------------------------------------------------*/ |
41 | ADC_HandleTypeDef hadc; |
43 | ADC_HandleTypeDef hadc; |
42 | DMA_HandleTypeDef hdma_adc; |
44 | DMA_HandleTypeDef hdma_adc; |
Line 49... | Line 51... | ||
49 | UART_HandleTypeDef huart1; |
51 | UART_HandleTypeDef huart1; |
50 | UART_HandleTypeDef huart2; |
52 | UART_HandleTypeDef huart2; |
51 | 53 | ||
52 | /* USER CODE BEGIN PV */ |
54 | /* USER CODE BEGIN PV */ |
53 | /* Private variables ---------------------------------------------------------*/ |
55 | /* Private variables ---------------------------------------------------------*/ |
54 | char TimerFlag = 0; |
- | |
55 | 56 | ||
- | 57 | ||
- | 58 | // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000 |
|
- | 59 | // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the first pulse longer than 1/300 of a second as being a proper closure . |
|
- | 60 | // the TIM2 counter counts in 10uS increments, |
|
- | 61 | ||
- | 62 | #define BREAKER_MIN (RPM_COUNT_RATE/300) |
|
- | 63 | ||
- | 64 | ||
- | 65 | volatile char TimerFlag = 0; |
|
- | 66 | ||
56 | char NoSerialInCTR = 0; // Missing characters coming in on USART1 |
67 | volatile char NoSerialInCTR = 0; // Missing characters coming in on USART1 |
57 | char NoSerialIn = 0; |
68 | volatile char NoSerialIn = 0; |
58 | 69 | ||
59 | // storage for ADC |
70 | // storage for ADC |
60 | long ADC_samples[6]; |
71 | long ADC_samples[6]; |
61 | 72 | ||
- | 73 | // Rev counter processing from original RevCounter Project |
|
- | 74 | unsigned int RPM_Diff = 0; |
|
- | 75 | unsigned int RPM_Count_Latch = 0; |
|
- | 76 | // accumulators |
|
- | 77 | unsigned int RPM_Pulsecount = 0; |
|
- | 78 | unsigned int RPM_FilteredWidth = 0; |
|
- | 79 | ||
- | 80 | unsigned int Coded_RPM = 0; |
|
- | 81 | unsigned int Coded_CHT = 0; |
|
- | 82 | ||
62 | /* USER CODE END PV */ |
83 | /* USER CODE END PV */ |
63 | 84 | ||
64 | /* Private function prototypes -----------------------------------------------*/ |
85 | /* Private function prototypes -----------------------------------------------*/ |
65 | void SystemClock_Config(void); |
86 | void SystemClock_Config(void); |
66 | void Error_Handler(void); |
87 | void Error_Handler(void); |
Line 77... | Line 98... | ||
77 | 98 | ||
78 | 99 | ||
79 | /* USER CODE BEGIN PFP */ |
100 | /* USER CODE BEGIN PFP */ |
80 | /* Private function prototypes -----------------------------------------------*/ |
101 | /* Private function prototypes -----------------------------------------------*/ |
81 | 102 | ||
- | 103 | /* USER CODE END PFP */ |
|
82 | 104 | ||
83 | void ConfigureDMA(void) |
105 | /* USER CODE BEGIN 0 */ |
84 | { |
106 | |
- | 107 | void ConfigureDMA(void) { |
|
85 | hdma_adc.Instance = DMA1_Channel1; |
108 | hdma_adc.Instance = DMA1_Channel1; |
86 | hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; |
109 | hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; |
87 | hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; |
110 | hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; |
88 | hdma_adc.Init.MemInc = DMA_MINC_ENABLE; |
111 | hdma_adc.Init.MemInc = DMA_MINC_ENABLE; |
89 | hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; |
112 | hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; |
90 | hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; |
113 | hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; |
91 | hdma_adc.Init.Mode = DMA_CIRCULAR; // make the DMA loop automatically |
114 | hdma_adc.Init.Mode = DMA_CIRCULAR; // make the DMA loop automatically |
92 | hdma_adc.Init.Priority = DMA_PRIORITY_LOW; |
115 | hdma_adc.Init.Priority = DMA_PRIORITY_LOW; |
93 | HAL_DMA_Init(&hdma_adc); |
116 | HAL_DMA_Init(&hdma_adc); |
94 | __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); |
117 | __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); |
- | 118 | ||
- | 119 | } |
|
- | 120 | ||
- | 121 | void plx_sendword(int x) { |
|
- | 122 | PutCharSerial(&uc1, ((x) >> 6) & 0x3F); |
|
- | 123 | PutCharSerial(&uc1, (x) & 0x3F); |
|
- | 124 | } |
|
- | 125 | ||
- | 126 | void ProcessRPM(int instance) { |
|
- | 127 | // compute the timer values |
|
- | 128 | // snapshot timers |
|
- | 129 | unsigned long RPM_Pulsewidth; |
|
- | 130 | unsigned long RPM_Count_Val; |
|
- | 131 | __disable_irq(); // copy the counter value |
|
- | 132 | RPM_Count_Val = RPM_Count; |
|
- | 133 | __enable_irq(); |
|
- | 134 | // do calculations |
|
- | 135 | // if there is only one entry, cannot get difference |
|
- | 136 | if (RPM_Count_Latch != RPM_Count_Val) { |
|
- | 137 | while (1) { |
|
- | 138 | unsigned int base_time; |
|
- | 139 | unsigned int new_time; |
|
- | 140 | // if we are at N-1, stop. |
|
- | 141 | unsigned int next_count = RPM_Count_Latch + 1; |
|
- | 142 | if (next_count == RPM_SAMPLES) { |
|
- | 143 | next_count = 0; |
|
- | 144 | } |
|
- | 145 | if (next_count == RPM_Count_Val) { |
|
- | 146 | break; |
|
- | 147 | } |
|
- | 148 | base_time = RPM_Time[RPM_Count_Latch]; |
|
- | 149 | new_time = RPM_Time[next_count]; |
|
- | 150 | RPM_Count_Latch = next_count; |
|
- | 151 | if (new_time > base_time) { |
|
- | 152 | RPM_Pulsewidth = new_time - base_time; // not wrapped |
|
- | 153 | } else { |
|
- | 154 | RPM_Pulsewidth = new_time + (~base_time) + 1; // deal with wrapping |
|
- | 155 | } |
|
- | 156 | ||
- | 157 | RPM_Diff += RPM_Pulsewidth; |
|
- | 158 | // need to check if this is a long pulse. If it is, keep the answer |
|
- | 159 | if (RPM_Pulsewidth > BREAKER_MIN) { |
|
- | 160 | RPM_Pulsecount++; // count one pulse |
|
- | 161 | RPM_FilteredWidth += RPM_Diff; // add its width to the accumulator |
|
- | 162 | RPM_Diff = 0; // reset accumulator of all the narrow widths |
|
- | 163 | } |
|
- | 164 | } |
|
- | 165 | ||
- | 166 | } |
|
- | 167 | ||
- | 168 | if (RPM_Pulsecount > 0) { |
|
- | 169 | ||
- | 170 | // now have time for N pulses in clocks |
|
- | 171 | // need to scale by 19.55: one unit is 19.55 RPM |
|
- | 172 | // 1Hz is 60 RPM |
|
- | 173 | Coded_RPM = (30.0 / 19.55 * RPM_Pulsecount * RPM_COUNT_RATE) |
|
- | 174 | / (RPM_FilteredWidth) + 0.5; |
|
- | 175 | #if !defined MY_DEBUG |
|
- | 176 | // reset here unless we want to debug |
|
- | 177 | RPM_Pulsecount = 0; |
|
- | 178 | RPM_FilteredWidth = 0; |
|
- | 179 | #endif |
|
- | 180 | } |
|
95 | 181 | ||
- | 182 | // send the current RPM calculation |
|
- | 183 | plx_sendword(PLX_RPM); |
|
- | 184 | PutCharSerial(&uc1, instance); |
|
- | 185 | plx_sendword(Coded_RPM); |
|
96 | } |
186 | } |
97 | 187 | ||
98 | /* USER CODE END PFP */ |
- | |
99 | 188 | ||
- | 189 | // this uses a MAX6675 which is a simple 16 bit read |
|
- | 190 | // SPI is configured for 8 bits so I can use an OLED display if I need it |
|
- | 191 | void ProcessCHT(int instance) |
|
- | 192 | { |
|
- | 193 | uint8_t buffer[2]; |
|
- | 194 | HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, SPI_NS_Temp_Pin, GPIO_PIN_RESET); |
|
- | 195 | ||
- | 196 | ||
- | 197 | HAL_SPI_Receive(&hspi1, buffer, 2, 2); |
|
- | 198 | ||
- | 199 | HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, SPI_NS_Temp_Pin, GPIO_PIN_SET); |
|
- | 200 | ||
- | 201 | ||
- | 202 | uint16_t obs = (buffer[0]<<8)| buffer[1]; |
|
- | 203 | ||
- | 204 | uint8_t good = (obs & 4)==0; |
|
- | 205 | if(good) |
|
- | 206 | { |
|
100 | /* USER CODE BEGIN 0 */ |
207 | Coded_CHT = obs>>5; |
- | 208 | } |
|
- | 209 | plx_sendword(PLX_EGT); |
|
- | 210 | PutCharSerial(&uc1, instance); |
|
- | 211 | plx_sendword(Coded_CHT); |
|
- | 212 | ||
- | 213 | } |
|
101 | 214 | ||
102 | /* USER CODE END 0 */ |
215 | /* USER CODE END 0 */ |
103 | 216 | ||
104 | int main(void) |
217 | int main(void) |
105 | { |
218 | { |
Line 126... | Line 239... | ||
126 | MX_USART1_UART_Init(); |
239 | MX_USART1_UART_Init(); |
127 | MX_USART2_UART_Init(); |
240 | MX_USART2_UART_Init(); |
128 | 241 | ||
129 | /* USER CODE BEGIN 2 */ |
242 | /* USER CODE BEGIN 2 */ |
130 | 243 | ||
131 | __HAL_RCC_SPI1_CLK_ENABLE() ; // Temp sensor port |
244 | __HAL_RCC_SPI1_CLK_ENABLE() |
- | 245 | ; // Temp sensor port |
|
132 | __HAL_RCC_USART1_CLK_ENABLE() ; // PLX comms port |
246 | __HAL_RCC_USART1_CLK_ENABLE() |
- | 247 | ; // PLX comms port |
|
133 | __HAL_RCC_USART2_CLK_ENABLE() ; // Debug comms port |
248 | __HAL_RCC_USART2_CLK_ENABLE() |
- | 249 | ; // Debug comms port |
|
134 | 250 | ||
135 | __HAL_RCC_ADC1_CLK_ENABLE(); // enable the ADC |
251 | __HAL_RCC_ADC1_CLK_ENABLE() |
- | 252 | ; // enable the ADC |
|
136 | 253 | ||
- | 254 | __HAL_RCC_TIM6_CLK_ENABLE() |
|
- | 255 | ; |
|
137 | 256 | ||
138 | __HAL_RCC_TIM6_CLK_ENABLE(); |
- | |
139 | - | ||
140 | ConfigureDMA(); |
257 | ConfigureDMA(); |
141 | // HAL_ADC_Start_DMA(&g_AdcHandle, g_ADCBuffer, ADC_BUFFER_LENGTH); |
258 | // HAL_ADC_Start_DMA(&g_AdcHandle, g_ADCBuffer, ADC_BUFFER_LENGTH); |
142 | 259 | ||
143 | /* setup the USART control blocks */ |
260 | /* setup the USART control blocks */ |
144 | init_usart_ctl(&uc1, huart1.Instance); |
261 | init_usart_ctl(&uc1, huart1.Instance); |
145 | init_usart_ctl(&uc2, huart2.Instance); |
262 | init_usart_ctl(&uc2, huart2.Instance); |
146 | 263 | ||
147 | EnableSerialRxInterrupt(&uc1); |
264 | EnableSerialRxInterrupt(&uc1); |
148 | EnableSerialRxInterrupt(&uc2); |
265 | EnableSerialRxInterrupt(&uc2); |
149 | 266 | ||
150 | HAL_TIM_Base_Start_IT(&htim6); |
267 | HAL_TIM_Base_Start_IT(&htim6); |
151 | 268 | ||
152 | PutCharSerial(&uc2,'A'); |
269 | PutCharSerial(&uc2, 'A'); |
153 | 270 | ||
154 | /* USER CODE END 2 */ |
271 | /* USER CODE END 2 */ |
155 | 272 | ||
156 | /* Infinite loop */ |
273 | /* Infinite loop */ |
157 | /* USER CODE BEGIN WHILE */ |
274 | /* USER CODE BEGIN WHILE */ |
158 | while (1) |
275 | while (1) { |
159 | { |
- | |
160 | /* USER CODE END WHILE */ |
276 | /* USER CODE END WHILE */ |
161 | 277 | ||
162 | /* USER CODE BEGIN 3 */ |
278 | /* USER CODE BEGIN 3 */ |
- | 279 | // check to see if we have any incoming data, copy and append if so, if no data then create our own frames. |
|
- | 280 | int c; |
|
- | 281 | char send = 0; |
|
- | 282 | ||
- | 283 | // poll the input for a stop bit or timeout |
|
- | 284 | if(PollSerial(&uc1)) |
|
- | 285 | { |
|
- | 286 | c = GetCharSerial(&uc1); |
|
- | 287 | if (c != PLX_Stop) |
|
- | 288 | { |
|
- | 289 | PutCharSerial(&uc1,c); // echo all but the stop bit |
|
- | 290 | } else { // must be a stop character |
|
- | 291 | send = 1; // start our sending process. |
|
- | 292 | } |
|
- | 293 | } |
|
- | 294 | ||
- | 295 | // sort out auto-sending |
|
- | 296 | if (TimerFlag) |
|
- | 297 | { |
|
- | 298 | if (NoSerialIn) |
|
- | 299 | { |
|
- | 300 | PutCharSerial(&uc1,PLX_Start); |
|
- | 301 | send = 1; |
|
- | 302 | } |
|
- | 303 | } |
|
- | 304 | if (send) |
|
- | 305 | { |
|
- | 306 | send = 0; |
|
163 | 307 | ||
- | 308 | ProcessRPM(0); |
|
- | 309 | ProcessCHT(0); |
|
- | 310 | ||
- | 311 | PutCharSerial(&uc1,PLX_Stop); |
|
164 | } |
312 | } |
- | 313 | ||
- | 314 | } |
|
165 | /* USER CODE END 3 */ |
315 | /* USER CODE END 3 */ |
166 | 316 | ||
167 | } |
317 | } |
168 | 318 | ||
169 | /** System Clock Configuration |
319 | /** System Clock Configuration |
Line 571... | Line 721... | ||
571 | * @retval None |
721 | * @retval None |
572 | */ |
722 | */ |
573 | void Error_Handler(void) |
723 | void Error_Handler(void) |
574 | { |
724 | { |
575 | /* USER CODE BEGIN Error_Handler */ |
725 | /* USER CODE BEGIN Error_Handler */ |
576 | /* User can add his own implementation to report the HAL error return state */ |
726 | /* User can add his own implementation to report the HAL error return state */ |
577 | while(1) |
727 | while (1) { |
578 | { |
- | |
579 | } |
728 | } |
580 | /* USER CODE END Error_Handler */ |
729 | /* USER CODE END Error_Handler */ |
581 | } |
730 | } |
582 | 731 | ||
583 | #ifdef USE_FULL_ASSERT |
732 | #ifdef USE_FULL_ASSERT |
584 | 733 | ||
Line 590... | Line 739... | ||
590 | * @retval None |
739 | * @retval None |
591 | */ |
740 | */ |
592 | void assert_failed(uint8_t* file, uint32_t line) |
741 | void assert_failed(uint8_t* file, uint32_t line) |
593 | { |
742 | { |
594 | /* USER CODE BEGIN 6 */ |
743 | /* USER CODE BEGIN 6 */ |
595 | /* User can add his own implementation to report the file name and line number, |
744 | /* User can add his own implementation to report the file name and line number, |
596 | ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ |
745 | ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ |
597 | /* USER CODE END 6 */ |
746 | /* USER CODE END 6 */ |
598 | 747 | ||
599 | } |
748 | } |
600 | 749 | ||
601 | #endif |
750 | #endif |