hw_encoder.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include "board.h"
  2. typedef struct
  3. {
  4. TIM_TypeDef *base; //对象实体
  5. uint16_t irqn; //中断源
  6. uint16_t period; //一圈的总脉冲数
  7. } hw_tim_encoder_t;
  8. typedef struct
  9. {
  10. GPIO_TypeDef *aport; //端口
  11. unsigned short apin; //引脚
  12. GPIO_TypeDef *bport; //方向功能端口
  13. unsigned short bpin; //方向功能引脚
  14. unsigned short af; //复用功能位置
  15. } hw_encode_pin_t;
  16. static hw_encode_pin_t pin_maps[HW_ENCODER_NUMBER] = {
  17. { GPIOA, 0, GPIOA, 1, 2 }
  18. };
  19. static hw_tim_encoder_t encoders[HW_ENCODER_NUMBER] = {
  20. TIM5, TIM5_IRQn,10000
  21. };
  22. #define HW_TIM5_TO_ENCODER 0
  23. static int encoder_cycles[HW_ENCODER_NUMBER] = {
  24. 0
  25. };
  26. void TIM5_IRQHandler(void) {
  27. int count = TIM5->CNT;
  28. if (TIM5->SR & (1 << 0)) {
  29. //if (count + 1 == encoders[HW_TIM5_TO_ENCODER].period) { //正转加一圈
  30. if (TIM5->CR1 & (1 << 4)) {
  31. encoder_cycles[HW_TIM5_TO_ENCODER]--;
  32. }
  33. //}
  34. //else if (count == 0) { //反转减一圈
  35. else if ((TIM5->CR1 & (1 << 4)) == 0) {
  36. encoder_cycles[HW_TIM5_TO_ENCODER]++;
  37. }
  38. //}
  39. TIM5->SR &= ~(1 << 0);
  40. }
  41. }
  42. /**
  43. * 读取编码器当前值
  44. *
  45. * @author LXZ (042020)
  46. *
  47. * @param index
  48. *
  49. * @return int
  50. */
  51. int hw_encoder_get(int index)
  52. {
  53. int cycle = 0;
  54. int value = 0;
  55. do
  56. {
  57. cycle = encoder_cycles[index];
  58. value = encoders[index].base->CNT;
  59. } while(cycle != encoder_cycles[index]);
  60. return cycle * encoders[index].period + value;
  61. }
  62. /**
  63. * 设置编码器当前值
  64. *
  65. * @author LXZ (042020)
  66. *
  67. * @param index
  68. * @param count
  69. */
  70. void hw_encoder_set(int index, int count)
  71. {
  72. encoder_cycles[index] = count / encoders[index].period;
  73. encoders->base->CNT = count % encoders[index].period;
  74. }
  75. /**
  76. * 编码器接口初始化
  77. *
  78. * @author LXZ (010420)
  79. *
  80. * @param void
  81. */
  82. void hw_encoder_init(void) {
  83. int index = 0;
  84. while (index < HW_ENCODER_NUMBER) {
  85. hw_encode_pin_t *ecoder_pin = &pin_maps[index];
  86. uint32_t port = (uint32_t)ecoder_pin->aport;
  87. uint16_t pin = ecoder_pin->apin;
  88. uint16_t af = ecoder_pin->af;
  89. if (port >= GPIOA_BASE &&
  90. port <= GPIOJ_BASE) {
  91. RCC->AHB1ENR |= 1 << ((port - GPIOA_BASE) / 0x400);
  92. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  93. GPIO_MODE_AF,
  94. GPIO_OTYPE_PP,
  95. GPIO_SPEED_100M,
  96. GPIO_PUPD_PU);
  97. GPIO_AF_Set((GPIO_TypeDef *)port, pin, af);
  98. }
  99. port = (uint32_t)ecoder_pin->bport;
  100. pin = ecoder_pin->bpin;
  101. if (port >= GPIOA_BASE &&
  102. port <= GPIOJ_BASE) {
  103. RCC->AHB1ENR |= 1 << ((port - GPIOA_BASE) / 0x400);
  104. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  105. GPIO_MODE_AF,
  106. GPIO_OTYPE_PP,
  107. GPIO_SPEED_100M,
  108. GPIO_PUPD_PU);
  109. GPIO_AF_Set((GPIO_TypeDef *)port, pin, af);
  110. }
  111. index++;
  112. }
  113. index = 0;
  114. while (index < HW_ENCODER_NUMBER) {
  115. hw_tim_encoder_t *coder = &encoders[index];
  116. uint32_t tim_base = (uint32_t)coder->base;
  117. TIM_TypeDef *timx = coder->base;
  118. if (tim_base >= TIM2_BASE && tim_base <= TIM14_BASE) {
  119. uint32_t en_mask = 1 << ((tim_base - TIM2_BASE) / 0x400);
  120. do {
  121. RCC->APB1ENR |= en_mask;
  122. } while (RCC->APB1ENR & en_mask == 0);
  123. }
  124. else if (tim_base >= TIM1_BASE && tim_base <= TIM11_BASE) {
  125. uint32_t en_mask = 1 << ((tim_base - TIM1_BASE) / 0x400);
  126. do {
  127. RCC->APB2ENR |= en_mask;
  128. } while (RCC->APB2ENR & en_mask == 0);
  129. }
  130. else {
  131. do {
  132. //无效的定时器
  133. } while (1);
  134. }
  135. //初始化定时器
  136. timx->PSC = 0;
  137. timx->ARR = coder->period; //编码器一圈脉冲数
  138. timx->SMCR = 0;
  139. timx->DIER |= 1 << 0; //使能更新中断
  140. timx->CR1 &= ~(3 << 8); //不分频
  141. timx->CR1 &= ~(3 << 5); //边沿计数模式
  142. timx->CR1 &= ~(1 << 4); //向上计数
  143. timx->CR1 |= (1 << 2); //限制只有上溢中断
  144. //timx->CR1 |= (1 << 7); //ARR寄存器不缓冲
  145. timx->CR2 = 0;
  146. timx->CCER =0; //使能PWM通道
  147. timx->CCMR1 = 0;
  148. timx->CCMR2 = 0;
  149. timx->SMCR = 0;
  150. timx->CNT = 0;
  151. timx->SMCR = 3 << 0; //使能双边编码器接口
  152. timx->CCMR1 = (1 << 0) | (3 << 4) | (1 << 8) | (3 << 12); //使能T1、T2映射
  153. timx->CCER |= (1 << 0) | (1 << 4); //使能捕获通道1、2
  154. timx->SR = 0;
  155. timx->CR1 |= 1 << 0; //开启定时器
  156. MY_NVIC_Init(1, 3, coder->irqn, 2);
  157. index++;
  158. index++;
  159. }
  160. }