【解析新特性】300W单路输出工业电源>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 一步一步玩转两轮智能自平衡小车----by GaoMjun

共21条 1/3 1 2 3 跳转至

一步一步玩转两轮智能自平衡小车----by GaoMjun

菜鸟
2015-07-12 03:31:11    评分

其实搞小车已经有一段时间了,到目前为止小车的基本程序已基本搞定,昨天已经把mpu6050的dmp调通,接下来就是一些数据的处理,也是自平衡小车的算法核心,这才是重中之重

顺便说以下我项目托管在Github,想要研究的同学直接clone我的项目到本地即可

项目地址:https://github.com/GaoMjun/balancer

在本贴的最下方有pdf文档,有需要的同学可以下载


1. 提前 建立基础工程:http://forum.eepw.com.cn/thread/274707/1

2.实验点亮LED:http://forum.eepw.com.cn/thread/274707/1#2

3.实验 闪:http://forum.eepw.com.cn/thread/274707/1#3

4.实验三 重定向printf:http://forum.eepw.com.cn/thread/274707/1#4

5.实验四 UART实现控制台:http://forum.eepw.com.cn/thread/274707/1#5

6.实验五 编码器读取车轮转速:http://forum.eepw.com.cn/thread/274707/1#6

7.实验六 PWM驱动电机:http://forum.eepw.com.cn/thread/274707/1#8



提前 建立基础工程


1. 首先建立如下文件

balancer - startup 启动汇编文件

|- cmsis      cortex3 内核必要文件

|- lib           stm32 官方标准库文件

|- MDKProj  keil 工程建立在此

|- driver 自己将要编写的各种驱动, 各位主要在此发挥

|- user 用户目录,主要是 main.c


2. stm32 官方标准库文件,点此下载

在网页最下方


点击 download 下载即可

下载完成之后解压

1. Libraries->STM32F10x_StdPeriph_Driver 下的 inc src 复制到上面的 lib

2. Libraries->CMSIS->CM3->CoreSupport 下的 core_cm3.ccore_cm3.h Libraries->CMSIS->CM3->DeviceSupport->ST->STM32F10x下的stm32f10x.h , system_stm32f10x.c, system_stm32f10x.h复制到上面的cmsis

3. Libraries->CMSIS->CM3->DeviceSupport->ST->STM32F10x-> startup->arm 下的 startup_stm32f10x_md.s 复制到上面的startup

4. Project->STM32F10x_StdPeriph_Template下的

main.c stm32f10x_conf.h stm32f10x_it.c stm32f10x_it.h复制到上面的user

3. 打开Keil uVision然后Project->New uVision Project

然后浏览到上面建立的MDKProj目录下,起个名字,比如balancer, 然后save

然后选择器件,找到STM32F103C8,然后OK

接下来,NO

然后

出现下图

然后编辑成这样

然后开始Add Files,添加上面复制的一些 .s .c文件,如下

startup-|- startup_stm32f10x_md.s

cmsis-|- core_cm3.c

|- system_stm32f10x.c

lib-|- misc.c

|- stm32f10x_adc.c

|- stm32f10x_gpio.c

|- stm32f10x_rcc.c

|- stm32f10x_tim.c

|- stm32f10x_usart.c

user-|-main.c

|- stm32f10x_it.c

接下来

出现

C/C++这一项很重要

按照下面选择好,然后OK

再接下来将main.c改成这样

继续

然后再全部编译一次,如果编译成功,恭喜基础工程到此结束

NEXT 点灯


本教程pdf文档百度云下载:http://pan.baidu.com/s/1hqm0bw4 提取密码:——回复可见内容——




关键词: 玩转     两轮     智能     平衡     小车    

菜鸟
2015-07-12 15:58:42    评分
2楼

实验点亮LED

1.  将前面建立好的基工程base复制一份并改个名字比如day1_led

2.  打开day1_led里工程,新建空白文档

3.  然后起个名字保存到driver

4.  再新建空白文档led.h保存到driver

明一下文件的,几乎所有的文件都是成,里的led.cled.h,目完全按照官方函数

led.c --  1. 首先包含led.h

    2. 态变量申明

    3.静态函数申明

    4.静态函数实现

    5.其他函数实现

led.h -- 1.条件编译申明

             2..c文件所用到的一些宏定义

             3..c文件所用到的一些结构体变量

             4..c中其他原函数的申明

5.下面开始正式编写

所有的驱动编写基本都有如下步骤

1.         1. RCC_Configuration         打开时钟

2.         2. GPIO_Configuration        配置GPIO引脚

3.         3. NVIC_Configuration        如果是中断实现,则在此配置中断,否则没有

下面开始逐个实现

1.    首先配置时钟,我们先来看下官方文档


从上图中可以看出所有的GPIO都在APB2

在看一下我们的小车电路板原理图


小车上有两个led,红灯是电源灯,蓝灯是工作灯,也就是上图的L1,从原理图中可知其接在PB8,也就是GPIOB的第八个管脚上

剩下的就是调用库函数了,最后

led.c
#include "led.h"

static void RCC_Configuration(void);
static void GPIO_Configuration(void);

static void RCC_Configuration(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}

static void GPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void led_init(void)
{
	RCC_Configuration();
	GPIO_Configuration();
}

void led_on(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_8);
}

void led_off(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_8);
}


led.h
#ifndef __LED_H_
#define __LED_H_

#include "stm32f10x.h"

void led_init(void);
void led_on(void);
void led_off(void);

#endif

main.c
#include "led.h"

int main()
{
	SystemInit();
	led_init();

	led_on();

	while(1)
	{}
}

好了打完收工

 

NEXT 让灯闪

 


菜鸟
2015-07-12 16:29:47    评分
3楼

实验

1.     将上个实验的工程day1_led复制一份并改名位day2_flash_led

2.     打开工程文件并新建空白文档delay.cdelay.h都保存到driver,

stm32一个SysTick,今天我们就利用这个定时器以中断方式实现较为精确的延时,并且利用此延时程序,让小车的蓝色工作闪烁起来

3.  此程序在官方例程里面有,在这里我们只要简单的改动就可以移植到我们的工程中所以在这里废话不多说,直接给出代码

 

delay.c

#include "delay.h"

 

static __IO u32 TimingDelay;

 

void delay_init(void)

{

            if(SysTick_Config(SystemCoreClock / 1000000))

            {

                        while(1);

            }

}

 

void DelayUs(__IO u32 nTime)

{

            TimingDelay = nTime;

 

            while(TimingDelay != 0);

}

 

void DelayMs(__IO u32 nTime)

{

            DelayUs(nTime * 1000);

}

 

void TimingDelay_Decrement(void)

{

            if(TimingDelay != 0x00)

                        {

                                    TimingDelay--;

                        }

}

 

 

 

 

 

delay.h

#ifndef __DELAY_H_

#define __DELAY_H_

 

#include "stm32f10x.h"

 

void delay_init(void);

void DelayUs(__IO u32 nTime);

void DelayMs(__IO u32 nTime);

void TimingDelay_Decrement(void);

 

 

#endif

 

stm32f10x_it.c

#include “delay.h”

 

void SysTick_Handler(void)

{

                        TimingDelay_Decrement();

}

 

main.c

#include "led.h"

#include "delay.h"

 

int main(void)

{

            SystemInit();

            led_init();

            delay_init();

           

            while(1)

            {

                        led_on();

                        DelayMs(500);

                        led_off();

                        DelayMs(500);

            }

}

 

NEXT 重定向printf

 

 


菜鸟
2015-07-13 00:24:15    评分
4楼

实验三 重定向printf

1. printfC言的出函数,它的大与方便是每个学习过C言同学都知道的,但是标准的printf出到端屏幕的,stm32上哪里有玩意二,stm32上最常用的莫于串口了,常用串口出一写调试信息,方便到家调试,所以今天我就把printf拿来用用,它直接出到串口

2. 不得不,printf各种,各种格式化,要是我自己实现printf,那不是每个人都有那个能力的,里重定向printf基本可以保留printf所有的特性,再加上stm32,使用printf几乎不会造成性能的

3. 首先将base基础工程复制一份并重命名位day3_printf,打开此工程并新建两个空白文档并命名为uart1.cuart1.h保存到driver目录下

4. 重定向printf之前首先要驱动USART

STM32F103C83USART,的小物尽其用,三个串口都用到了

1. UART1 – 此串口就是用于本试验的重定向printf

2. UART2 – 此串口是超声波模用的,我没有此模,so …

3. UART3 – 此串口用于牙通信, 控制小,也就是实现串口consola控制台

5. 驱动UART首先是3步舒适化

1. RCC_Configuration USART1APB2

2. GPIO_Configuration   PA9 – Tx  PA10 – Rx

3. NVIC_Configuration   USART1_IRQn

6.  printf是基于字符串输出流fputc实现的,因此我们只要简单的改写fputc就可以

下面给出完整代码

uart1.c

#include "uart1.h"

static void RCC_Configuration(void);

static void GPIO_Configuration(void);

static void NVIC_Configuration(void);

static void RCC_Configuration(void)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, EBABLE);

}

static void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

static void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

void uart1_init(void)

{

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = 115200;

USART_InitStructure.USART_WordLength =       USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART1,&USART_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

USART_Cmd(USART1, ENABLE);

RCC_Configuration();

GPIO_Configuration();

NVIC_Configuration();

}

PUTCHAR_PROTOTYPE

{

USART_SendData(USART1, (uint16_t)ch);

while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)

{}

return ch;

}

uart1.h

#ifndef __UART1_H_

#define __UART1_H_

#include "stm32f10x.h"

#include "stdio.h"

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#define GETCHAR_PROTOTYPE int fgetc(FILE *f)

void uart1_init(void);

#endif

main.c

#include "stm32f10x.h"

#include

#include "uart1.h"

int main(void)

{

SystemInit();

uart1_init();

while(1)

{

printf("Hello World! \r\n");

}

}

注意使用MicroLib库编译


NEXT 串口实现控制台



菜鸟
2015-07-13 11:23:56    评分
5楼

实验四 UART实现控制台

一.     将实验三day3_printf工程复制一份并改名为day4_consola

 

二.     本试验在调试时用UART1进行实验,后期可以改为UART3用与蓝牙串口通信,对小车进行控制

 

三.     stm32f10x_it.c添加中断服务程序

stm32f10x_it.c

extern char Uart1_Buffer[];

extern uint8_t Uart1_BufferSize;

extern uint8_t commandEnd;

void USART1_IRQHandler()

{

    uint16_t tmpData;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

    {

        USART_ClearITPendingBit(USART1, USART_IT_RXNE);

       

        if(USART_ReceiveData(USART1) == '\r')

        {

             commandEnd = 1;

             printf("\r\n");

        }

        if(USART_ReceiveData(USART1) == '\b')

        {

             printf("\b ");

        }

       

        tmpData = USART_ReceiveData(USART1);

        sprintf(&Uart1_Buffer[Uart1_BufferSize ++], "%c", tmpData);

        Uart1_BufferSize &= 0xFF;

        USART_SendData(USART1, tmpData);

    }

}

 

四.     main.c中实现命令控制

main.c

#include <stdio.h>

#include <string.h>

 

#include "led.h"

#include "uart1.h"

 

char Uart1_Buffer[0xFF] = "0";

char command1[0xFF] = "led on";

char command2[0xFF] = "led off";

uint16_t Uart1_BufferSize = 0;

uint8_t commandEnd = 0;

 

int main(void)

{

    SystemInit();

    led_init();

    delay_init();

    uart1_init();

       

    while(1)

    {      

        if(commandEnd)

        {

             commandEnd = 0;

            

             Uart1_Buffer[Uart1_BufferSize-1] = '\0';

             if(0 == strcmp(Uart1_Buffer, command1))

                 led_on();

             else if(!strcmp(Uart1_Buffer, command2))

                 led_off();

             else

                 printf("unknow command \r\n");

            

             Uart1_BufferSize = 0;

        }      

    }

}

 

 

NEXT 编码器读取车轮转速

 


菜鸟
2015-07-14 00:26:14    评分
6楼

实验五 编码器读取车轮转速

一. 利用定时器的计数器去计数单位时间内小车车轮上的编码器的栅格数目,就可以获得车轮的转速

二. 读取车速应该是在定时中断时读取的,这样才是单位时间”,才可以计算出车轮角速度,所以在用这里用TIM15ms产生一个中断,在中断时分别用TIM2TIM4读取左右两个车轮的编码器的值,最后用printf打印数值.注意:在这里用printf输出数据量很大会阻塞主程序,但在这里只是方便调试

三. day3_printf工程复制一份并重命名为day5_encoder,打开工程

四. 首先驱动TIM15ms产生一个中断

新建两个空白文档命名为timer1.ctimer.h并都保存到driver目录下

最后完整代码如下

timer1.c

#include "timer1.h"

static void RCC_Configuration(void);

static void NVIC_Configuration(void);

static void RCC_Configuration(void)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

}

static void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

void timer1_init(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_Configuration();

NVIC_Configuration();

TIM_DeInit(TIM1);

TIM_TimeBaseStructure.TIM_Period = 50 - 1;

TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1;

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

TIM_ClearFlag(TIM1, TIM_FLAG_Update);

TIM_ITConfig(TIM1, TIM_IT_Update,ENABLE);

TIM_Cmd(TIM1, ENABLE);

}

timer1.h

#ifndef __TIMER1_H_

#define __TIMER1_H_

#include "stm32f10x.h"

void timer1_init(void);

#endif

五. 驱动TIM2TIM4去给两个轮子编码器的值

再新建两个空白文档命名为encoder.cencoder.h并都保存到driver目录下

encoder.c

#include "encoder.h"

static void RCC_Configuration(void);

static void GPIO_Configuration(void);

static void timer_init(void);

static void RCC_Configuration(void)

{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 |

RCC_APB1Periph_TIM4, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |

RCC_APB2Periph_GPIOB, ENABLE);

}

static void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

GPIO_Init(GPIOB, &GPIO_InitStructure);

}

static void timer_init(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_DeInit(TIM2);

TIM_DeInit(TIM4);

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //65535

TIM_TimeBaseStructure.TIM_Prescaler = 0x0;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

TIM_EncoderInterfaceConfig(TIM2,

TIM_EncoderMode_TI12,

TIM_ICPolarity_Rising,

TIM_ICPolarity_Rising);

TIM_EncoderInterfaceConfig(TIM4,

TIM_EncoderMode_TI12,

TIM_ICPolarity_Rising,

TIM_ICPolarity_Rising);

TIM2->CNT = 0x0;

TIM4->CNT = 0x0;

TIM_Cmd(TIM2,ENABLE);

TIM_Cmd(TIM4,ENABLE);

}

void encoder_init(void)

{

RCC_Configuration();

GPIO_Configuration();

timer_init();

}

int32_t get_left_encoder_num(void)

{

return TIM_GetCounter(TIM2);

}

int32_t get_right_encoder_num(void)

{

return TIM_GetCounter(TIM4);

}

encoder.h

#ifndef __ENCODER_H_

#define __ENCODER_H_

#include "stm32f10x.h"

void encoder_init(void);

int32_t get_left_encoder_num(void);

int32_t get_right_encoder_num(void);

#endif

六. 然后在stm32f10x_it.c加入中断服务程序

stm32f10x_it.c

void TIM1_UP_IRQHandler(void)

{

if(TIM_GetITStatus(TIM1, TIM_FLAG_Update) != RESET)

{

TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);

printf("left:%d    right:%d \r\n", get_left_encoder_num(), get_right_encoder_num());

}

}













NEXT 驱动电机




菜鸟
2015-07-14 10:44:25    评分
7楼
3q...................................................

菜鸟
2015-07-15 00:36:14    评分
8楼

实验六 PWM驱动电机

一.     本试验以TIM3产生PWM波驱动电机以不同的速度运转

二.     STM32F103C8的一个定时器可以同时产生四路不同占空比的方波即PWM,我们的小车只有两个电机,所以只要产生两路PWM即可,列外,在硬件电路路已经为我们决定好了用那两路 [左右电机顺序随便]

三.     因为电机需要很大的电流才能驱动,单靠IO口的驱动能力是远远不够的,因此我们的小车使用了TB6612驱动电机,列外它还可以用它内部的H桥式电路控制电机的转向

借用老师的两张图片

有了这两张图的说明就可以编写程序控制电机了

四.     将实验五的工程day5_encoder复制一份并重命名为day6_motor,直接利用实验五的程序可以直接读出我们设定的电机转速

五.     新建两个空白文档并分别命名为motor.cmotor.h保存到driver目录下

下面是完整代码

 

motor.c

#include "motor.h"

 

static void RCC_Configuration(void);

static void GPIO_Configuration(void);

static void timer3_init(void);

 

static void RCC_Configuration(void)

{

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

}

 

static void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

 

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

}

 

static void timer3_init(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

 

    //2.time base config

// TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_Period = 3600 - 1;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

 

    //3.pwm1 mode config channel3

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  

   

    /* PWM1 Mode configuration: Channel3 */  

    TIM_OCInitStructure.TIM_Pulse = 0;  

    TIM_OC3Init(TIM3, &TIM_OCInitStructure);

    TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  

  

    /* PWM1 Mode configuration: Channel4 */  

    TIM_OCInitStructure.TIM_Pulse = 0;  

    TIM_OC4Init(TIM3, &TIM_OCInitStructure);  

    TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

 

    TIM_ARRPreloadConfig(TIM3, ENABLE);

 

    //5. timer3 anable counter

    TIM_Cmd(TIM3,ENABLE);

}

 

void motor_init(void)

{

    RCC_Configuration();

    GPIO_Configuration();

    timer3_init();

 

    motor_stop();

}

 

void motor_stop(void)

{

    //1.left motor

    GPIO_ResetBits(GPIOB,GPIO_Pin_12);

    GPIO_ResetBits(GPIOB,GPIO_Pin_13);

 

    //2.right motor

    GPIO_ResetBits(GPIOB,GPIO_Pin_14);

    GPIO_ResetBits(GPIOB,GPIO_Pin_15);

}

 

void set_motor_speed(int16_t left_motor, int16_t right_motor)

{

    if(left_motor > 0)

    {

        GPIO_SetBits(GPIOB,GPIO_Pin_12);

        GPIO_ResetBits(GPIOB,GPIO_Pin_13);

    }

    else

    {

        GPIO_ResetBits(GPIOB,GPIO_Pin_12);

        GPIO_SetBits(GPIOB,GPIO_Pin_13);

        left_motor = -left_motor;

    }

 

    if(right_motor > 0)

    {

        GPIO_ResetBits(GPIOB,GPIO_Pin_14);

        GPIO_SetBits(GPIOB,GPIO_Pin_15);

    }

    else

    {

        GPIO_SetBits(GPIOB,GPIO_Pin_14);

        GPIO_ResetBits(GPIOB,GPIO_Pin_15);

        right_motor = -right_motor;

    }

 

    TIM_SetCompare3(TIM3, left_motor);

    TIM_SetCompare4(TIM3, right_motor);

}

 

 

motor.h

#ifndef __MOTOR_H_

#define __MOTOR_H_

 

#include "stm32f10x.h"

 

void motor_init(void);

void motor_stop(void);

void set_motor_speed(int16_t left_motor, int16_t right_motor);

 

#endif

 

main.c中测试

main.c

#include "stm32f10x.h"

 

#include "stdio.h"

 

#include "led.h"

#include "delay.h"

#include "uart1.h"

#include "consola.h"

#include "encoder.h"

#include "timer1.h"

#include "motor.h"

 

int main(void)

{

    SystemInit();

    led_init();

    delay_init();

    uart1_init();

    encoder_init();

    timer1_init();

    motor_init();

 

    set_motor_speed(100, 100);

 

    while(1)

    {

        led_on();

        delayMs(100);

        led_off();

        delayMs(100);

    }

}

 

NEXT 获取电池电压

 


助工
2015-08-01 19:44:50    评分
9楼
感谢你的分享,我正寻思着用库写一个编码器的程序呢。

菜鸟
2015-08-10 19:30:01    评分
10楼
刚开始学,谢谢分享

共21条 1/3 1 2 3 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]