main.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /**
  2. ******************************************************************************
  3. * @file China AC-meter
  4. * @author Vladimir N. Shilov <shilow@ukr.net>
  5. * @version V0.0.1
  6. * @date 2016.11.09
  7. * @brief Main program body
  8. ******************************************************************************
  9. * @attention
  10. *
  11. * ----------------------------------------------------------------------------
  12. * "THE BEER-WARE LICENSE" (Revision 42):
  13. * <shilow@ukr.net> wrote this file. As long as you retain this notice you
  14. * can do whatever you want with this stuff. If we meet some day, and you think
  15. * this stuff is worth it, you can buy me a beer in return. Shilov V.N.
  16. * ----------------------------------------------------------------------------
  17. *
  18. ******************************************************************************
  19. */
  20. /* Includes ------------------------------------------------------------------*/
  21. #include "stm8s.h"
  22. //#include "rtos.h"
  23. /* Private defines -----------------------------------------------------------*/
  24. // for 1 msek ticks
  25. #define TIM4_PERIOD (uint8_t)124
  26. #define ADC_PORT GPIOD
  27. #define ADC_PINS GPIO_PIN_3
  28. #define ADC_CHNL ADC1_CHANNEL_4
  29. #define ADC_SCHT ADC1_SCHMITTTRIG_CHANNEL4
  30. #define ADC_SMPLS 64
  31. // Supply voltage in mili volts
  32. #define ADC_VREF 3335
  33. // input OA multiplier -- [(3.6/0.68) + 1) * 1000]
  34. #define ADC_MULT 6294
  35. // shunt resistance in mili Ohms
  36. #define ADC_SHUNT 50
  37. #define BTN_PORT (GPIOA)
  38. #define BTN_PINS (GPIO_PIN_2)
  39. /*
  40. AAA
  41. F B
  42. F B
  43. GGG
  44. E C
  45. E C
  46. DDD P
  47. */
  48. #define LED_ANOD1_PORT GPIOA
  49. #define LED_ANOD1_PIN GPIO_PIN_3
  50. #define LED_ANOD2_PORT GPIOD
  51. #define LED_ANOD2_PIN GPIO_PIN_6
  52. #define LED_ANOD3_PORT GPIOD
  53. #define LED_ANOD3_PIN GPIO_PIN_4
  54. #define LED_SEG1_PORT GPIOA
  55. #define LED_SEG1_PINS GPIO_PIN_1
  56. #define LED_SEG_F GPIO_PIN_1
  57. #define LED_SEG2_PORT GPIOB
  58. #define LED_SEG2_PINS (GPIO_PIN_5 | GPIO_PIN_4)
  59. #define LED_SEG_A GPIO_PIN_5
  60. #define LED_SEG_B GPIO_PIN_4
  61. #define LED_SEG3_PORT GPIOC
  62. #define LED_SEG3_PINS (GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_3 | GPIO_PIN_5)
  63. #define LED_SEG_G GPIO_PIN_3
  64. #define LED_SEG_C GPIO_PIN_4
  65. #define LED_SEG_P GPIO_PIN_5
  66. #define LED_SEG_D GPIO_PIN_6
  67. #define LED_SEG_E GPIO_PIN_7
  68. #define LED_OUT_OFF {LED_SEG1_PORT->ODR |= LED_SEG1_PINS; LED_SEG2_PORT->ODR |= LED_SEG2_PINS; LED_SEG3_PORT->ODR |= LED_SEG3_PINS;}
  69. #define LED_OUT_DP GPIOC->ODR &= (~LED_SEG_P);
  70. #define LED_OUT_MM GPIOC->ODR &= LED_SEG_G;
  71. #define LED_OUT_0 GPIOA->ODR &= 0xFD; GPIOB->ODR &= 0xCF; GPIOC->ODR &= 0x29;
  72. #define LED_OUT_1 GPIOB->ODR &= 0xEF; GPIOC->ODR &= 0xE9;
  73. #define LED_OUT_2 GPIOB->ODR &= 0xCF; GPIOC->ODR &= 0x31;
  74. #define LED_OUT_3 GPIOB->ODR &= 0xCF; GPIOC->ODR &= 0xA1;
  75. #define LED_OUT_4 GPIOA->ODR &= 0xFD; GPIOB->ODR &= 0xEF; GPIOC->ODR &= 0xE1;
  76. #define LED_OUT_5 GPIOA->ODR &= 0xFD; GPIOB->ODR &= 0xDF; GPIOC->ODR &= 0xA1;
  77. #define LED_OUT_6 GPIOA->ODR &= 0xFD; GPIOB->ODR &= 0xDF; GPIOC->ODR &= 0x21;
  78. #define LED_OUT_7 GPIOB->ODR &= 0xCF; GPIOC->ODR &= 0xE9;
  79. #define LED_OUT_8 GPIOA->ODR &= 0xFD; GPIOB->ODR &= 0xCF; GPIOC->ODR &= 0x21;
  80. #define LED_OUT_9 GPIOA->ODR &= 0xFD; GPIOB->ODR &= 0xCF; GPIOC->ODR &= 0xA1;
  81. #define LED_ANODE_OFF {LED_ANOD1_PORT->ODR &= ~LED_ANOD1_PIN; GPIOD->ODR &= ~(LED_ANOD2_PIN | LED_ANOD3_PIN);}
  82. #define LED_ANODE_ON1 LED_ANOD1_PORT->ODR |= LED_ANOD1_PIN;
  83. #define LED_ANODE_ON2 LED_ANOD2_PORT->ODR |= LED_ANOD2_PIN;
  84. #define LED_ANODE_ON3 LED_ANOD3_PORT->ODR |= LED_ANOD3_PIN;
  85. #define SUB_SECOND_CNT 5
  86. #define LED_ONE_PERIOD 5
  87. #define ADC_ZERO_EEADDR FLASH_DATA_START_PHYSICAL_ADDRESS
  88. /* Private function prototypes -----------------------------------------------*/
  89. static void ADC_CorrectZero(void);
  90. static void ADC_Config(void);
  91. static void GPIO_Config(void);
  92. static void TIM1_Config(void);
  93. static void TIM4_Config(void);
  94. static void OutputToLed(void);
  95. static void PrepareForLed(void);
  96. //static void CountCapacity(void);
  97. /* Private functions ---------------------------------------------------------*/
  98. /* Private variables ---------------------------------------------------------*/
  99. __IO uint16_t ConversionBuffer[ADC_SMPLS];
  100. __IO uint8_t BufferIndex = 0;
  101. __IO uint8_t LedCnt = 0;
  102. static uint16_t Current = 0;
  103. static uint32_t Capacity = 0;
  104. static uint8_t LedDigits[3] = {0, 0, 0};
  105. static uint8_t LedPoint = 3;
  106. static uint16_t SubSecondBfr = 0;
  107. static uint8_t SubSecondCnt = SUB_SECOND_CNT;
  108. static uint16_t ADC_ZeroFix = 0;
  109. void main(void)
  110. {
  111. /* Initialization of the clock to 16MHz */
  112. CLK->CKDIVR = 0x00;
  113. /* Disable clock of unused perephireal */
  114. /* UART, SPI, I2C */
  115. CLK->PCKENR1 = 0xF0;
  116. /* CAN */
  117. CLK->PCKENR2 = 0x0F;
  118. /* SWIM clock */
  119. CLK->SWIMCCR = 0x00;
  120. /* GPIO configuration ------------------------------------------*/
  121. GPIO_Config();
  122. /* ADC configuration -------------------------------------------*/
  123. ADC_Config();
  124. /* TIM1 configuration -----------------------------------------*/
  125. TIM1_Config();
  126. /* Initialize dispatcher */
  127. //RTOS_Init();
  128. //RTOS_SetTask(OutputToLed, 0, 5);
  129. //RTOS_SetTask(PrepareForLed, 210, 200);
  130. //RTOS_SetTask(CountCapacity, 1005, 1000);
  131. /* TIM4 configuration -----------------------------------------*/
  132. TIM4_Config();
  133. /* enable interrupts */
  134. enableInterrupts();
  135. /** If btn pin == 0 -- auto fix adc zero level
  136. else -- read zero value from eeprom
  137. Value stored in MSB:LSB
  138. */
  139. if((BTN_PORT->IDR & BTN_PINS) == 0){
  140. ADC_CorrectZero();
  141. } else {
  142. ADC_ZeroFix = (uint16_t)(FLASH_ReadByte(ADC_ZERO_EEADDR) << 8);
  143. ADC_ZeroFix |= FLASH_ReadByte((ADC_ZERO_EEADDR+1));
  144. }
  145. /* Infinite loop */
  146. while (1)
  147. {
  148. if (LedCnt >= LED_ONE_PERIOD) {
  149. LedCnt = 0;
  150. OutputToLed();
  151. }
  152. if (BufferIndex >= ADC_SMPLS) {
  153. BufferIndex = 0;
  154. /* Oversampling */
  155. uint32_t tbuf = 0;
  156. uint8_t i = 0;
  157. for(i=0; i<ADC_SMPLS; i++){
  158. tbuf += ConversionBuffer[i];
  159. }
  160. if(tbuf > ADC_ZeroFix){
  161. tbuf -= ADC_ZeroFix;
  162. tbuf >>= 3; // ïðåäâàðèòåëüíûé äåëèòåëü îâåðñåìïëèíãà
  163. tbuf *= ADC_VREF; // Ìíîæèì íà îïîðíîå íàïðÿæåíèå
  164. tbuf = (tbuf + 4096) / 8191; // get ADC input voltage in mV
  165. tbuf *= 1000; // êîìïåíñàöèÿ êîýô. óñèëåíèÿ âõîäíîãî ÎÓ
  166. tbuf *= 1000; // êîìïåíñàöèÿ ñîïðîòèâëåíèÿ øóíòà
  167. tbuf = (tbuf + (ADC_MULT/2)) / ADC_MULT; // get voltage from shunt
  168. /* â Current òîê â ìèëèàìïåðàõ */
  169. Current = (tbuf + (ADC_SHUNT/2)) / ADC_SHUNT;
  170. SubSecondBfr += Current;
  171. }
  172. SubSecondCnt --;
  173. if(SubSecondCnt == 0){
  174. Capacity += ( (SubSecondBfr + (SUB_SECOND_CNT/2)) / SUB_SECOND_CNT );
  175. SubSecondBfr = 0;
  176. SubSecondCnt = SUB_SECOND_CNT;
  177. }
  178. PrepareForLed();
  179. } // End of if (BufferIndex >= ADC_SMPLS)
  180. //RTOS_DispatchTask();
  181. wfi();
  182. } // End of infinity
  183. } // End of main()
  184. /** Êîððåêòèðóåì íàïðÿæåíèå ñìåùåíèÿ íóëÿ ÎÓ íà âõîäå ÀÖÏ */
  185. static void ADC_CorrectZero(void) {
  186. /* æä¸ì îêîí÷àíèÿ öèêëà èçìåðåíèé */
  187. do {
  188. } while (BufferIndex < ADC_SMPLS);
  189. BufferIndex = 0;
  190. /* Ïîëó÷àåì 16-òè áèòíîå çíà÷åíèå îò ÀÖÏ */
  191. uint8_t i = 0;
  192. for(i=0; i<ADC_SMPLS; i++){
  193. ADC_ZeroFix += ConversionBuffer[i];
  194. }
  195. /* Ñîõðàíÿåì ïîëó÷åííîå çíà÷åíèå â EEPROM */
  196. /*Define FLASH programming time*/
  197. FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);
  198. /* Unlock Data memory */
  199. FLASH_Unlock(FLASH_MEMTYPE_DATA);
  200. /* MSB */
  201. FLASH_ProgramByte(ADC_ZERO_EEADDR, (uint8_t)(ADC_ZeroFix>>8));
  202. /* LSB */
  203. FLASH_ProgramByte((ADC_ZERO_EEADDR+1), (uint8_t)(ADC_ZeroFix));
  204. /* Lock Data memory */
  205. FLASH_Lock(FLASH_MEMTYPE_DATA);
  206. }
  207. /** Prepare current value for output ot led */
  208. static void PrepareForLed(void) {
  209. uint16_t value;
  210. if((BTN_PORT->IDR & BTN_PINS) == 0){
  211. value = Capacity / 3600;
  212. } else {
  213. value = Current;
  214. }
  215. if(value > 9999){
  216. /* XX.X Amper */
  217. LedPoint = 1;
  218. LedDigits[0] = value / 10000;
  219. value = value % 10000;
  220. LedDigits[1] = value / 1000;
  221. LedDigits[2] = (value % 1000) / 100;
  222. } else if(value > 999){
  223. /* X.XX Amper */
  224. LedPoint = 0;
  225. LedDigits[0] = value / 1000;
  226. value = value % 1000;
  227. LedDigits[1] = value / 100;
  228. LedDigits[2] = (value % 100) / 10;
  229. } else {
  230. /* XXX mili Amper */
  231. LedPoint = 3;
  232. LedDigits[0] = value / 100;
  233. value = value % 100;
  234. LedDigits[1] = value / 10;
  235. LedDigits[2] = value % 10;
  236. }
  237. }
  238. /** Output current value to next led */
  239. static void OutputToLed(void) {
  240. static uint8_t ledn = 0;
  241. /* íà ïèíå PD2 äîëæåí áûòü ìåàäð ñ ïåðèîäîì 10 ìñåê. */
  242. GPIOD->ODR ^= GPIO_PIN_2;
  243. /* all off */
  244. //LED_ANODE_OFF
  245. LED_ANOD1_PORT->ODR &= ~LED_ANOD1_PIN;
  246. LED_ANOD2_PORT->ODR &= ~(LED_ANOD2_PIN | LED_ANOD3_PIN);
  247. //LED_OUT_OFF
  248. LED_SEG1_PORT->ODR |= LED_SEG1_PINS;
  249. LED_SEG2_PORT->ODR |= LED_SEG2_PINS;
  250. LED_SEG3_PORT->ODR |= LED_SEG3_PINS;
  251. /* out next value */
  252. switch(LedDigits[ledn]){
  253. case 0:
  254. LED_OUT_0
  255. break;
  256. case 1:
  257. LED_OUT_1
  258. break;
  259. case 2:
  260. LED_OUT_2
  261. break;
  262. case 3:
  263. LED_OUT_3
  264. break;
  265. case 4:
  266. LED_OUT_4
  267. break;
  268. case 5:
  269. LED_OUT_5
  270. break;
  271. case 6:
  272. LED_OUT_6
  273. break;
  274. case 7:
  275. LED_OUT_7
  276. break;
  277. case 8:
  278. LED_OUT_8
  279. break;
  280. case 9:
  281. LED_OUT_9
  282. break;
  283. default:
  284. LED_OUT_MM
  285. }
  286. if(ledn == LedPoint) {
  287. LED_OUT_DP
  288. }
  289. /* Fire on nex led */
  290. switch(ledn){
  291. case 0:
  292. LED_ANODE_ON1
  293. ledn = 1;
  294. break;
  295. case 1:
  296. LED_ANODE_ON2
  297. ledn = 2;
  298. break;
  299. case 2:
  300. LED_ANODE_ON3
  301. ledn = 0;
  302. break;
  303. default:
  304. ledn = 0;
  305. }
  306. }
  307. /**
  308. * @brief Configure GPIO for LEDs and buttons available on the evaluation board
  309. * @param None
  310. * @retval None
  311. */
  312. static void GPIO_Config(void)
  313. {
  314. /* Initialize LEDs */
  315. GPIO_Init(LED_ANOD1_PORT, (GPIO_Pin_TypeDef)LED_ANOD1_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
  316. GPIO_Init(LED_ANOD2_PORT, (GPIO_Pin_TypeDef)(LED_ANOD2_PIN | LED_ANOD3_PIN), GPIO_MODE_OUT_PP_LOW_FAST);
  317. GPIO_Init(LED_SEG1_PORT, (GPIO_Pin_TypeDef)LED_SEG1_PINS, GPIO_MODE_OUT_PP_LOW_FAST);
  318. GPIO_Init(LED_SEG2_PORT, (GPIO_Pin_TypeDef)LED_SEG2_PINS, GPIO_MODE_OUT_PP_LOW_FAST);
  319. GPIO_Init(LED_SEG3_PORT, (GPIO_Pin_TypeDef)LED_SEG3_PINS, GPIO_MODE_OUT_PP_LOW_FAST);
  320. /* Initialize Button pin */
  321. GPIO_Init(BTN_PORT, (GPIO_Pin_TypeDef)BTN_PINS, GPIO_MODE_IN_PU_NO_IT);
  322. /* Init GPIO for ADC */
  323. GPIO_Init(ADC_PORT, (GPIO_Pin_TypeDef)ADC_PINS, GPIO_MODE_IN_FL_NO_IT);
  324. /* Test output */
  325. GPIO_Init(GPIOD, (GPIO_Pin_TypeDef)GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);
  326. }
  327. /**
  328. * @brief Configure ADC.
  329. * @param None
  330. * @retval None
  331. */
  332. static void ADC_Config()
  333. {
  334. /* De-Init ADC peripheral*/
  335. ADC1_DeInit();
  336. /* Init ADC1 peripheral */
  337. ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC_CHNL, ADC1_PRESSEL_FCPU_D8, \
  338. ADC1_EXTTRIG_TIM, ENABLE, ADC1_ALIGN_RIGHT, ADC_SCHT, DISABLE);
  339. /* Enable EOC interrupt */
  340. ADC1_ITConfig(ADC1_IT_EOCIE, ENABLE);
  341. /*Start Conversion */
  342. //ADC1_StartConversion();
  343. }
  344. /**
  345. * @brief Configure TIM1.
  346. * @param None
  347. * @retval None
  348. */
  349. static void TIM1_Config(void)
  350. {
  351. TIM1_DeInit();
  352. /* Time Base configuration */
  353. /*
  354. Timer period - 3,125 ms
  355. TIM1_Period = 50
  356. TIM1_Prescaler = 1000
  357. TIM1_CounterMode = TIM1_COUNTERMODE_UP
  358. TIM1_RepetitionCounter = 0
  359. */
  360. TIM1_TimeBaseInit(999, TIM1_COUNTERMODE_UP, 49, 0);
  361. /* Trigrer configuration */
  362. TIM1_SelectOutputTrigger(TIM1_TRGOSOURCE_UPDATE);
  363. /* Update Interrupt Enable */
  364. //TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
  365. /* Enable TIM1 */
  366. TIM1_Cmd(ENABLE);
  367. }
  368. /**
  369. * @brief Configure TIM4.
  370. * @param None
  371. * @retval None
  372. */
  373. static void TIM4_Config(void)
  374. {
  375. TIM4_DeInit();
  376. /*
  377. TIM4 configuration:
  378. - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
  379. clock used is 16 MHz / 128 = 125 000 Hz
  380. - With 125 000 Hz we can generate time base:
  381. max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
  382. min time base is 0.016 ms if TIM4_PERIOD = 1 --> ( 1 + 1) / 125000 = 0.016 ms
  383. - In this example we need to generate a time base equal to 1 ms
  384. so TIM4_PERIOD = (0.001 * 125000 - 1) = 124
  385. */
  386. /* Time base configuration */
  387. TIM4_TimeBaseInit(TIM4_PRESCALER_128, TIM4_PERIOD);
  388. /* Clear TIM4 update flag */
  389. TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  390. /* Enable update interrupt */
  391. TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
  392. /* Enable TIM4 */
  393. TIM4_Cmd(ENABLE);
  394. }
  395. #ifdef USE_FULL_ASSERT
  396. /**
  397. * @brief Reports the name of the source file and the source line number
  398. * where the assert_param error has occurred.
  399. * @param file: pointer to the source file name
  400. * @param line: assert_param error line source number
  401. * @retval : None
  402. */
  403. void assert_failed(u8* file, u32 line)
  404. {
  405. /* User can add his own implementation to report the file name and line number,
  406. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  407. /* Infinite loop */
  408. while (1)
  409. {
  410. }
  411. }
  412. #endif
  413. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/