123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #include "board.h"
- typedef struct
- {
- TIM_TypeDef *base; //对象实体
- uint16_t irqn; //中断源
- uint16_t period; //一圈的总脉冲数
- } hw_tim_encoder_t;
- typedef struct
- {
- GPIO_TypeDef *aport; //端口
- unsigned short apin; //引脚
- GPIO_TypeDef *bport; //方向功能端口
- unsigned short bpin; //方向功能引脚
- unsigned short af; //复用功能位置
- } hw_encode_pin_t;
- static hw_encode_pin_t pin_maps[HW_ENCODER_NUMBER] = {
- { GPIOA, 0, GPIOA, 1, 2 }
- };
- static hw_tim_encoder_t encoders[HW_ENCODER_NUMBER] = {
- TIM5, TIM5_IRQn,10000
- };
- #define HW_TIM5_TO_ENCODER 0
- static int encoder_cycles[HW_ENCODER_NUMBER] = {
- 0
- };
- void TIM5_IRQHandler(void) {
- int count = TIM5->CNT;
- if (TIM5->SR & (1 << 0)) {
- //if (count + 1 == encoders[HW_TIM5_TO_ENCODER].period) { //正转加一圈
- if (TIM5->CR1 & (1 << 4)) {
- encoder_cycles[HW_TIM5_TO_ENCODER]--;
- }
- //}
- //else if (count == 0) { //反转减一圈
- else if ((TIM5->CR1 & (1 << 4)) == 0) {
- encoder_cycles[HW_TIM5_TO_ENCODER]++;
- }
- //}
- TIM5->SR &= ~(1 << 0);
- }
- }
- /**
- * 读取编码器当前值
- *
- * @author LXZ (042020)
- *
- * @param index
- *
- * @return int
- */
- int hw_encoder_get(int index)
- {
- int cycle = 0;
- int value = 0;
- do
- {
- cycle = encoder_cycles[index];
- value = encoders[index].base->CNT;
- } while(cycle != encoder_cycles[index]);
- return cycle * encoders[index].period + value;
- }
- /**
- * 设置编码器当前值
- *
- * @author LXZ (042020)
- *
- * @param index
- * @param count
- */
- void hw_encoder_set(int index, int count)
- {
- encoder_cycles[index] = count / encoders[index].period;
- encoders->base->CNT = count % encoders[index].period;
- }
- /**
- * 编码器接口初始化
- *
- * @author LXZ (010420)
- *
- * @param void
- */
- void hw_encoder_init(void) {
- int index = 0;
- while (index < HW_ENCODER_NUMBER) {
- hw_encode_pin_t *ecoder_pin = &pin_maps[index];
- uint32_t port = (uint32_t)ecoder_pin->aport;
- uint16_t pin = ecoder_pin->apin;
- uint16_t af = ecoder_pin->af;
- if (port >= GPIOA_BASE &&
- port <= GPIOJ_BASE) {
- RCC->AHB1ENR |= 1 << ((port - GPIOA_BASE) / 0x400);
- GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
- GPIO_MODE_AF,
- GPIO_OTYPE_PP,
- GPIO_SPEED_100M,
- GPIO_PUPD_PU);
- GPIO_AF_Set((GPIO_TypeDef *)port, pin, af);
- }
- port = (uint32_t)ecoder_pin->bport;
- pin = ecoder_pin->bpin;
- if (port >= GPIOA_BASE &&
- port <= GPIOJ_BASE) {
- RCC->AHB1ENR |= 1 << ((port - GPIOA_BASE) / 0x400);
- GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
- GPIO_MODE_AF,
- GPIO_OTYPE_PP,
- GPIO_SPEED_100M,
- GPIO_PUPD_PU);
- GPIO_AF_Set((GPIO_TypeDef *)port, pin, af);
- }
-
- index++;
- }
- index = 0;
- while (index < HW_ENCODER_NUMBER) {
- hw_tim_encoder_t *coder = &encoders[index];
- uint32_t tim_base = (uint32_t)coder->base;
- TIM_TypeDef *timx = coder->base;
- if (tim_base >= TIM2_BASE && tim_base <= TIM14_BASE) {
- uint32_t en_mask = 1 << ((tim_base - TIM2_BASE) / 0x400);
- do {
- RCC->APB1ENR |= en_mask;
- } while (RCC->APB1ENR & en_mask == 0);
- }
- else if (tim_base >= TIM1_BASE && tim_base <= TIM11_BASE) {
- uint32_t en_mask = 1 << ((tim_base - TIM1_BASE) / 0x400);
- do {
- RCC->APB2ENR |= en_mask;
- } while (RCC->APB2ENR & en_mask == 0);
- }
- else {
- do {
- //无效的定时器
- } while (1);
- }
- //初始化定时器
- timx->PSC = 0;
- timx->ARR = coder->period; //编码器一圈脉冲数
- timx->SMCR = 0;
- timx->DIER |= 1 << 0; //使能更新中断
- timx->CR1 &= ~(3 << 8); //不分频
- timx->CR1 &= ~(3 << 5); //边沿计数模式
- timx->CR1 &= ~(1 << 4); //向上计数
- timx->CR1 |= (1 << 2); //限制只有上溢中断
- //timx->CR1 |= (1 << 7); //ARR寄存器不缓冲
- timx->CR2 = 0;
- timx->CCER =0; //使能PWM通道
- timx->CCMR1 = 0;
- timx->CCMR2 = 0;
- timx->SMCR = 0;
- timx->CNT = 0;
- timx->SMCR = 3 << 0; //使能双边编码器接口
- timx->CCMR1 = (1 << 0) | (3 << 4) | (1 << 8) | (3 << 12); //使能T1、T2映射
- timx->CCER |= (1 << 0) | (1 << 4); //使能捕获通道1、2
- timx->SR = 0;
- timx->CR1 |= 1 << 0; //开启定时器
- MY_NVIC_Init(1, 3, coder->irqn, 2);
- index++;
- index++;
- }
- }
|