- void SPI_Digital_Tube_Config(void)
- {
- SPI_InitTypeDef SPI_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
-
- /* Disable the SPI peripheral */
- SPI_Cmd(SPI2, DISABLE);
- /* Enable SCK, MOSI, MISO and NSS GPIO clocks */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
- RCC_AHBPeriphClockCmd(SPI_Digital_Tube_SCK_GPIO_CLK |
- SPI_Digital_Tube_MOSI_GPIO_CLK|
- SPI_Digital_Tube_NSS_GPIO_CLK, ENABLE);
-
- /* SPI pin mappings */
- GPIO_PinAFConfig(SPI_Digital_Tube_SCK_GPIO_PORT, SPI_Digital_Tube_SCK_SOURCE, SPI_Digital_Tube_SCK_AF);
- GPIO_PinAFConfig(SPI_Digital_Tube_MOSI_GPIO_PORT, SPI_Digital_Tube_MOSI_SOURCE, SPI_Digital_Tube_MOSI_AF);
- GPIO_PinAFConfig(SPI_Digital_Tube_MISO_GPIO_PORT, SPI_Digital_Tube_MISO_SOURCE, SPI_Digital_Tube_MISO_AF);
- GPIO_PinAFConfig(SPI_Digital_Tube_NSS_GPIO_PORT, SPI_Digital_Tube_NSS_SOURCE, SPI_Digital_Tube_NSS_AF);
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
- /* SPI SCK pin configuration */
- GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_SCK_PIN;
- GPIO_Init(SPI_Digital_Tube_SCK_GPIO_PORT, &GPIO_InitStructure);
- /* SPI MOSI pin configuration */
- GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_MOSI_PIN;
- GPIO_Init(SPI_Digital_Tube_MOSI_GPIO_PORT, &GPIO_InitStructure);
- /* SPI MISO pin configuration */
- GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_MISO_PIN;
- GPIO_Init(SPI_Digital_Tube_MISO_GPIO_PORT, &GPIO_InitStructure);
-
- /* SPI NSS pin configuration */
- GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_NSS_PIN;
- GPIO_Init(SPI_Digital_Tube_NSS_GPIO_PORT, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_NSS_PIN;
- GPIO_Init(SPI_Digital_Tube_NSS_GPIO_PORT, &GPIO_InitStructure);
-
- /* SPI configuration -------------------------------------------------------*/
- SPI_I2S_DeInit(SPI2);
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
- // SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
- SPI_InitStructure.SPI_CRCPolynomial = 7;
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
- SPI_Init(SPI2, &SPI_InitStructure);
- /* Initialize the FIFO threshold */
- SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
-
- /* Enable the SPI peripheral */
- SPI_Cmd(SPI2, ENABLE);
-
- // /* Enable NSS output for master mode */
- // SPI_SSOutputCmd(SPI2, ENABLE);
- }
使用TIM6作为定时器,配置代码如下(1ms定时周期):
- static void BASIC_TIM_Mode_Config(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
- TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;//1ms
- TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;//47
- TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
- TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
- TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
- TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
- TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
- TIM_Cmd(BASIC_TIM, ENABLE);
- }
实际上每次只会有一个数码管亮,为了较好的视觉体验,将数码管进行千位百位十位个位循环显示,这样做的好处是4个数码管轮流显示,其亮度相同,避免出现一个数码管过亮的情形,影响视觉体验。数码管代码如下:
- void DisplayNumber(uint16_t num)
- {
- uint8_t mythousandNum,myhundredNum,mytenNum,myunitNum=0;
- if(num>9999)num=9999;
- mythousandNum=num/1000%10;
- myhundredNum=num/100%10;
- mytenNum=num/10%10;
- myunitNum=num%10;
- switch(mydisplaybit)
- {
- case thousaud:
- Display16(mythousandNum,4);
- mydisplaybit=hundred;
- break;
- case hundred:
- Display16(myhundredNum,3);
- mydisplaybit=ten;
- break;
- case ten:
- Display16(mytenNum,2);
- mydisplaybit=unit;
- break;
- case unit:
- Display16(myunitNum,1);
- mydisplaybit=thousaud;
- break;
- default:
- Display16(mythousandNum,4);
- mydisplaybit=hundred;
- break;
- }
- }
- static void Display16(uint8_t num,uint8_t place)
- {
- GPIO_ResetBits(SPI_Digital_Tube_NSS_GPIO_PORT, SPI_Digital_Tube_NSS_PIN);
- uint16_t Temp=((Num[num])<<8)+((0x01)<<(place-1));
- SPI2_Send_Byte16(Temp);
- GPIO_SetBits(SPI_Digital_Tube_NSS_GPIO_PORT, SPI_Digital_Tube_NSS_PIN);
- }
然后,每隔0.5s累加一次。在定时器中累计
- void TIM6_DAC_IRQHandler()
- {
- static uint16_t counter=0;
- static uint16_t num_buffer=0;
- if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET )
- {
- counter++;
- if(counter>499)
- {
- num_buffer++;
- counter=0;
- }
- DisplayNumber(num_buffer);
- TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);
- }
- }
显示的效果如下:
所以,初试成功。
试验第二步,让编码器说话。
首先,在STM32中配置编码器。
使用PA6和PA7作为定时器3的通道1和通道2,进行下图模式的计数。
即效果如下:
代码如下
- void TIM3_EncoderConfig(void)
- {
- TIM_ICInitTypeDef TIM_ICInitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- HALL_TIM_APBxClock_FUN(ENCODER_TIM_CLK, ENABLE);
- /* GPIOA clock enable */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //PA6 & PA7
- RCC_AHBPeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
- /* phase A & B*/
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);//TIM3_CH1
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);//TIM3_CH2
-
- TIM_DeInit(TIM3);
- TIM_TimeBaseStructure.TIM_Period =0xffff;
- TIM_TimeBaseStructure.TIM_Prescaler =0;
- TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
- TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
-
- TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
-
- TIM_ICStructInit(&TIM_ICInitStructure);
- TIM_ICInitStructure.TIM_ICFilter = 0;
- TIM_ICInit(TIM3, &TIM_ICInitStructure);
-
- // Clear all pending interrupts
- TIM_ClearFlag(TIM3, TIM_FLAG_Update);
- TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
- //Reset counter
- TIM_SetCounter(TIM3,0);
- TIM_Cmd(TIM3, ENABLE);
-
- /* Enable the TIM1 global Interrupt */
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
然后在中断服务函数中,将编码器的相对值计算出来,并根据编码器计数的相对变化,计算出电机的转速。具体代码如下:
- void TIM6_DAC_IRQHandler()
- {
- static uint16_t counter=0;
- static uint16_t num_buffer=0;
- static uint16_t temp_now=0;
- static uint16_t temp_pre=0;
- static uint16_t speed=0;
- if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET )
- {
- counter++;
- temp_now=(TIM_GetCounter(TIM3)&0xffff);
- if(counter>499)
- {
- num_buffer=(temp_now-temp_pre)>0?temp_now-temp_pre:temp_pre-temp_now;
- speed=100*num_buffer*60/64;
- counter=0;
- }
- DisplayNumber(speed);
- if(counter%10==0)temp_pre=temp_now;
- TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);
- }
- }
同时,为了防止TIM3中断溢出,记得清除中断标志位
- void TIM3_IRQHandler ()
- {
- if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
- {
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- }
- }
实际效果如下图所示(东西太多,手机不好拍动图,只能静物显示),可知,当电机电压9.32V时,转速为843rpm。当电压为18.7V时,转速为1687rpm。编码器的波形也用示波器显示出来了。还不错哈,哈哈哈
结论
本文使用STM32F0 discovery开发板,完成了编码器计数和电机转速的计算,并通过数码管将电机转速实时显示出来。