Implement simple servo control using PWM.
This commit is contained in:
parent
8b3a7c2237
commit
0f6545139b
@ -62,6 +62,7 @@ SRC_STM = \
|
||||
stm32f4xx_dma.c \
|
||||
stm32f4xx_exti.c \
|
||||
stm32f4xx_gpio.c \
|
||||
stm32f4xx_tim.c \
|
||||
stm_misc.c \
|
||||
usb_core.c \
|
||||
usb_dcd.c \
|
||||
|
@ -88,7 +88,7 @@ int lcd_line;
|
||||
int lcd_column;
|
||||
int lcd_next_line;
|
||||
|
||||
void lcd_init() {
|
||||
void lcd_init(void) {
|
||||
// set the outputs high
|
||||
PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_PIN;
|
||||
PYB_LCD_PORT->BSRRL = PYB_LCD_RST_PIN;
|
||||
|
@ -1,3 +1,3 @@
|
||||
void lcd_init();
|
||||
void lcd_init(void);
|
||||
void lcd_print_str(const char *str);
|
||||
void lcd_print_strn(const char *str, unsigned int len);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define PYB_LED_G1_PIN (GPIO_Pin_4)
|
||||
#define PYB_LED_G2_PIN (GPIO_Pin_5)
|
||||
|
||||
void led_init() {
|
||||
void led_init(void) {
|
||||
// set the output high (so LED is off)
|
||||
PYB_LED_R_PORT->BSRRL = PYB_LED_R1_PIN;
|
||||
PYB_LED_R_PORT->BSRRL = PYB_LED_R2_PIN;
|
||||
|
@ -5,6 +5,6 @@ typedef enum {
|
||||
PYB_LED_G2 = 3,
|
||||
} pyb_led_t;
|
||||
|
||||
void led_init();
|
||||
void led_init(void);
|
||||
void led_state(pyb_led_t led, int state);
|
||||
void led_toggle(pyb_led_t led);
|
||||
|
3366
stm/lib/stm32f4xx_tim.c
Normal file
3366
stm/lib/stm32f4xx_tim.c
Normal file
File diff suppressed because it is too large
Load Diff
1150
stm/lib/stm32f4xx_tim.h
Normal file
1150
stm/lib/stm32f4xx_tim.h
Normal file
File diff suppressed because it is too large
Load Diff
89
stm/main.c
89
stm/main.c
@ -2,6 +2,7 @@
|
||||
#include <stm32f4xx.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_tim.h>
|
||||
#include <stm_misc.h>
|
||||
#include "std.h"
|
||||
|
||||
@ -32,7 +33,7 @@ void flash_error(int n) {
|
||||
led_state(PYB_LED_R2, 0);
|
||||
}
|
||||
|
||||
static void impl02_c_version() {
|
||||
static void impl02_c_version(void) {
|
||||
int x = 0;
|
||||
while (x < 400) {
|
||||
int y = 0;
|
||||
@ -50,7 +51,7 @@ static void impl02_c_version() {
|
||||
#define PYB_USRSW_PORT (GPIOA)
|
||||
#define PYB_USRSW_PIN (GPIO_Pin_13)
|
||||
|
||||
void sw_init() {
|
||||
void sw_init(void) {
|
||||
// make it an input with pull-up
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = PYB_USRSW_PIN;
|
||||
@ -59,7 +60,7 @@ void sw_init() {
|
||||
GPIO_Init(PYB_USRSW_PORT, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
int sw_get() {
|
||||
int sw_get(void) {
|
||||
if (PYB_USRSW_PORT->IDR & PYB_USRSW_PIN) {
|
||||
// pulled high, so switch is not pressed
|
||||
return 0;
|
||||
@ -101,7 +102,7 @@ py_obj_t pyb_main(py_obj_t main) {
|
||||
}
|
||||
|
||||
// sync all file systems
|
||||
py_obj_t pyb_sync() {
|
||||
py_obj_t pyb_sync(void) {
|
||||
storage_flush();
|
||||
return py_const_none;
|
||||
}
|
||||
@ -116,7 +117,7 @@ py_obj_t pyb_led(py_obj_t state) {
|
||||
return state;
|
||||
}
|
||||
|
||||
py_obj_t pyb_sw() {
|
||||
py_obj_t pyb_sw(void) {
|
||||
if (sw_get()) {
|
||||
return py_const_true;
|
||||
} else {
|
||||
@ -131,7 +132,7 @@ void g(uint i) {
|
||||
nlr_jump((void*)(42 + i));
|
||||
}
|
||||
}
|
||||
void f() {
|
||||
void f(void) {
|
||||
nlr_buf_t nlr;
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
@ -149,12 +150,12 @@ void f() {
|
||||
}
|
||||
}
|
||||
}
|
||||
void nlr_test() {
|
||||
void nlr_test(void) {
|
||||
f(1);
|
||||
}
|
||||
*/
|
||||
|
||||
void fatality() {
|
||||
void fatality(void) {
|
||||
led_state(PYB_LED_R1, 1);
|
||||
led_state(PYB_LED_G1, 1);
|
||||
led_state(PYB_LED_R2, 1);
|
||||
@ -174,7 +175,7 @@ static const char fresh_boot_py[] =
|
||||
;
|
||||
|
||||
// get lots of info about the board
|
||||
static py_obj_t pyb_info() {
|
||||
static py_obj_t pyb_info(void) {
|
||||
// get and print clock speeds
|
||||
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
|
||||
{
|
||||
@ -249,7 +250,7 @@ int readline(vstr_t *line, const char *prompt) {
|
||||
}
|
||||
}
|
||||
|
||||
void do_repl() {
|
||||
void do_repl(void) {
|
||||
usb_vcp_send_str("Micro Python 0.5; STM32F405RG; PYBv2\r\n");
|
||||
usb_vcp_send_str("Type \"help\" for more information.\r\n");
|
||||
|
||||
@ -352,7 +353,7 @@ bool do_file(const char *filename) {
|
||||
|
||||
void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
|
||||
|
||||
void gc_collect() {
|
||||
void gc_collect(void) {
|
||||
uint32_t start = sys_tick_counter;
|
||||
gc_collect_start();
|
||||
gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
|
||||
@ -369,12 +370,70 @@ void gc_collect() {
|
||||
printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
|
||||
}
|
||||
|
||||
py_obj_t pyb_gc() {
|
||||
py_obj_t pyb_gc(void) {
|
||||
gc_collect();
|
||||
return py_const_none;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// PWM
|
||||
// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively
|
||||
// they are both 32-bit counters
|
||||
// 16-bit prescaler
|
||||
// TIM2_CH3 also on PB10 (used below)
|
||||
void servo_init(void) {
|
||||
// TIM2 clock enable
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||
|
||||
// GPIOC Configuration: TIM2_CH3 (PB10)
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
// Connect TIM2 pins to AF1
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
|
||||
|
||||
// Compute the prescaler value so TIM2 runs at 100kHz
|
||||
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 100000) - 1;
|
||||
|
||||
// Time base configuration
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TimeBaseStructure.TIM_Period = 2000; // timer cycles at 50Hz
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
|
||||
|
||||
// PWM1 Mode configuration: Channel1
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_Pulse = 150; // units of 10us
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
|
||||
|
||||
// ?
|
||||
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
|
||||
|
||||
// ?
|
||||
TIM_ARRPreloadConfig(TIM2, ENABLE);
|
||||
|
||||
// TIM2 enable counter
|
||||
TIM_Cmd(TIM2, ENABLE);
|
||||
}
|
||||
|
||||
py_obj_t pyb_servo_set(py_obj_t value) {
|
||||
int v = py_get_int(value);
|
||||
if (v < 100) { v = 100; }
|
||||
if (v > 200) { v = 200; }
|
||||
TIM2->CCR3 = v;
|
||||
return py_const_none;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// TODO disable JTAG
|
||||
|
||||
// set interrupt priority config to use all 4 bits for pre-empting
|
||||
@ -406,6 +465,9 @@ soft_reset:
|
||||
qstr_init();
|
||||
rt_init();
|
||||
|
||||
// servo
|
||||
servo_init();
|
||||
|
||||
// add some functions to the python namespace
|
||||
{
|
||||
py_obj_t m = py_module_new();
|
||||
@ -417,6 +479,7 @@ soft_reset:
|
||||
rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
|
||||
rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
|
||||
rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw));
|
||||
rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_1(pyb_servo_set));
|
||||
rt_store_name(qstr_from_str_static("pyb"), m);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ void *realloc(void *ptr, size_t n) {
|
||||
return gc_realloc(ptr, n);
|
||||
}
|
||||
|
||||
void __assert_func() {
|
||||
void __assert_func(void) {
|
||||
printf("\nASSERT FAIL!");
|
||||
for (;;) {
|
||||
}
|
||||
|
10
stm/mma.c
10
stm/mma.c
@ -6,7 +6,7 @@
|
||||
|
||||
#include "mma.h"
|
||||
|
||||
void mma_init() {
|
||||
void mma_init(void) {
|
||||
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1
|
||||
//gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
|
||||
//gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
|
||||
@ -46,7 +46,7 @@ void mma_init() {
|
||||
// set START bit in CR1 to generate a start cond!
|
||||
}
|
||||
|
||||
static uint32_t i2c_get_sr() {
|
||||
static uint32_t i2c_get_sr(void) {
|
||||
// must read SR1 first, then SR2, as the read can clear some flags
|
||||
uint32_t sr1 = I2C1->SR1;
|
||||
uint32_t sr2 = I2C1->SR2;
|
||||
@ -98,7 +98,7 @@ void mma_send_byte(uint8_t data) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mma_read_ack() {
|
||||
uint8_t mma_read_ack(void) {
|
||||
// enable ACK of received byte
|
||||
I2C1->CR1 |= I2C_CR1_ACK;
|
||||
// wait for BUSY, MSL and RXNE (byte received)
|
||||
@ -109,7 +109,7 @@ uint8_t mma_read_ack() {
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t mma_read_nack() {
|
||||
uint8_t mma_read_nack(void) {
|
||||
// disable ACK of received byte (to indicate end of receiving)
|
||||
I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
|
||||
// last byte should apparently also generate a stop condition
|
||||
@ -122,7 +122,7 @@ uint8_t mma_read_nack() {
|
||||
return data;
|
||||
}
|
||||
|
||||
void mma_stop() {
|
||||
void mma_stop(void) {
|
||||
// send stop condition
|
||||
I2C1->CR1 |= I2C_CR1_STOP;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
void mma_init();
|
||||
void mma_init(void);
|
||||
void mma_restart(uint8_t addr, int write);
|
||||
void mma_start(uint8_t addr, int write);
|
||||
void mma_send_byte(uint8_t data);
|
||||
uint8_t mma_read_ack();
|
||||
uint8_t mma_read_nack();
|
||||
void mma_stop();
|
||||
uint8_t mma_read_ack(void);
|
||||
uint8_t mma_read_nack(void);
|
||||
void mma_stop(void);
|
||||
|
@ -1,6 +1,6 @@
|
||||
typedef unsigned int size_t;
|
||||
|
||||
void __assert_func();
|
||||
void __assert_func(void);
|
||||
|
||||
void *malloc(size_t n);
|
||||
void free(void *ptr);
|
||||
|
@ -18,7 +18,7 @@ static uint32_t cache_flash_sector_start;
|
||||
static uint32_t cache_flash_sector_size;
|
||||
static bool cache_dirty;
|
||||
|
||||
static void cache_flush() {
|
||||
static void cache_flush(void) {
|
||||
if (cache_dirty) {
|
||||
// sync the cache RAM buffer by writing it to the flash page
|
||||
flash_write(cache_flash_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, cache_flash_sector_size / 4);
|
||||
@ -45,7 +45,7 @@ static uint8_t *cache_get_addr_for_write(uint32_t flash_addr) {
|
||||
return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
|
||||
}
|
||||
|
||||
void storage_init() {
|
||||
void storage_init(void) {
|
||||
if (!is_initialised) {
|
||||
cache_flash_sector_id = 0;
|
||||
cache_dirty = false;
|
||||
@ -53,15 +53,15 @@ void storage_init() {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t storage_get_block_size() {
|
||||
uint32_t storage_get_block_size(void) {
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
||||
uint32_t storage_get_block_count() {
|
||||
uint32_t storage_get_block_count(void) {
|
||||
return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS;
|
||||
}
|
||||
|
||||
void storage_flush() {
|
||||
void storage_flush(void) {
|
||||
cache_flush();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
void storage_init();
|
||||
uint32_t storage_get_block_size();
|
||||
uint32_t storage_get_block_count();
|
||||
void storage_flush();
|
||||
void storage_init(void);
|
||||
uint32_t storage_get_block_size(void);
|
||||
uint32_t storage_get_block_count(void);
|
||||
void storage_flush(void);
|
||||
bool storage_read_block(uint8_t *dest, uint32_t block);
|
||||
bool storage_write_block(const uint8_t *src, uint32_t block);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
volatile uint32_t sys_tick_counter;
|
||||
|
||||
void sys_tick_init() {
|
||||
void sys_tick_init(void) {
|
||||
// sys-tick interrupt called at 1ms intervals
|
||||
sys_tick_counter = 0;
|
||||
SysTick_Config(SystemCoreClock / 1000);
|
||||
@ -12,7 +12,7 @@ void sys_tick_init() {
|
||||
}
|
||||
|
||||
// called on SysTick interrupt
|
||||
void SysTick_Handler() {
|
||||
void SysTick_Handler(void) {
|
||||
sys_tick_counter++;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
extern volatile uint32_t sys_tick_counter;
|
||||
|
||||
void sys_tick_init();
|
||||
void SysTick_Handler();
|
||||
void sys_tick_init(void);
|
||||
void SysTick_Handler(void);
|
||||
void sys_tick_delay_ms(uint32_t delay_ms);
|
||||
void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
|
||||
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
|
||||
|
@ -19,7 +19,7 @@ static char rx_buf[64];
|
||||
static int rx_buf_in;
|
||||
static int rx_buf_out;
|
||||
|
||||
void usb_init() {
|
||||
void usb_init(void) {
|
||||
if (!is_enabled) {
|
||||
// only init USB once in the device's power-lifetime
|
||||
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
|
||||
@ -29,7 +29,7 @@ void usb_init() {
|
||||
is_enabled = 1;
|
||||
}
|
||||
|
||||
bool usb_vcp_is_enabled() {
|
||||
bool usb_vcp_is_enabled(void) {
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ void usb_vcp_receive(const char *buf, uint32_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
int usb_vcp_rx_any() {
|
||||
int usb_vcp_rx_any(void) {
|
||||
if (rx_buf_in >= rx_buf_out) {
|
||||
return rx_buf_in - rx_buf_out;
|
||||
} else {
|
||||
@ -58,7 +58,7 @@ int usb_vcp_rx_any() {
|
||||
}
|
||||
}
|
||||
|
||||
char usb_vcp_rx_get() {
|
||||
char usb_vcp_rx_get(void) {
|
||||
while (rx_buf_out == rx_buf_in) {
|
||||
}
|
||||
char c = rx_buf[rx_buf_out];
|
||||
|
@ -1,7 +1,7 @@
|
||||
void usb_init();
|
||||
bool usb_vcp_is_enabled();
|
||||
int usb_vcp_rx_any();
|
||||
char usb_vcp_rx_get();
|
||||
void usb_init(void);
|
||||
bool usb_vcp_is_enabled(void);
|
||||
int usb_vcp_rx_any(void);
|
||||
char usb_vcp_rx_get(void);
|
||||
void usb_vcp_send_str(const char* str);
|
||||
void usb_vcp_send_strn(const char* str, int len);
|
||||
void usb_vcp_send_strn_cooked(const char *str, int len);
|
||||
|
Loading…
Reference in New Issue
Block a user