diff --git a/src/drivers/adc.c b/src/drivers/adc.c new file mode 100644 index 0000000..214b1a9 --- /dev/null +++ b/src/drivers/adc.c @@ -0,0 +1,42 @@ +#include "adc.h" + +extern Clock_t sysclks; + +int adc_init(ADC_TypeDef* adc) { + // enable adc clock + if(adc == ADC1) RCC->APB2ENR |= 0x1 << 9; + else if(adc == ADC2) RCC->APB2ENR |= 0x1 << 10; + else return -1; //no such adc + + // enable adc + adc->CR2 |= 0x1; + + // configure regular channels + adc->CR1 = 0; //reset value + adc->CR1 |= 0x1 << 23; //enable analog watchdog + adc->CR1 |= 0x1 << 11; //discontinuous mode + + // set trigger to manual + adc->CR1 |= 0x7 << 3; + + adc->SMPR2 |= 0x7; + + // calibrate + adc->CR2 |= 0x1 << 2; + while((adc->CR2 >> 2) & 0x1); + + return 0; +} + +uint16_t adc_read(ADC_TypeDef* adc, uint8_t channel) { + + adc->SQR1 &= ~(0xF << 20); //one conversion only + adc->SQR3 = (adc->SQR3 & ~(0x1F)) | channel; //set channel + + //adc->CR2 |= 0x1 << 22; //start convertion + adc->CR2 |= 0x1; + while(!((adc->SR >> 1) & 0x1)); //waiting for convertion + + return adc->DR & 0xFFFF; + +} diff --git a/src/drivers/adc.h b/src/drivers/adc.h new file mode 100644 index 0000000..64fe6b4 --- /dev/null +++ b/src/drivers/adc.h @@ -0,0 +1,15 @@ +#ifndef ADC_H +#define ADC_H + +#include "../target/stm32f103xb.h" +#include "../config.h" +#include "rcc.h" + + +int adc_init(ADC_TypeDef* adc); + +uint16_t adc_read(ADC_TypeDef* adc, uint8_t channel); + + +#endif + diff --git a/src/drivers/rcc.c b/src/drivers/rcc.c index d2a6d12..5f4cacb 100644 --- a/src/drivers/rcc.c +++ b/src/drivers/rcc.c @@ -27,8 +27,8 @@ derived from the System clock (I2S, RTC, ADC, USB OTG FS/SDIO/RNG) ============================================================================== [..] A delay between an RCC peripheral clock enable and the effective peripheral -enabling should be taken into account in order to manage the peripheral read/write -from/to registers. +enabling should be taken into account in order to manage the peripheral +read/write from/to registers. (+) This delay depends on the peripheral mapping. (+) If peripheral is mapped on AHB: the delay is 2 AHB clock cycle after the clock enable bit is set on the hardware register @@ -66,6 +66,12 @@ register is required. /* PPLMUL: PPL multiplier */ #define RCC_CFGR_PLLMUL(fac) (fac + 2) +/* ADC: ADCPRE prescalers */ +#define RCC_CFGR_ADCPRE_DIV_2 0x0 +#define RCC_CFGR_ADCPRE_DIV_4 0x1 +#define RCC_CFGR_ADCPRE_DIV_6 0x2 +#define RCC_CFGR_ADCPRE_DIV_8 0x3 + enum rcc_osc { RCC_HSI, RCC_HSE, @@ -81,6 +87,7 @@ struct ClockConfig_t { uint8_t hpre; uint8_t ppre1; uint8_t ppre2; + uint8_t adcpre; uint32_t flash_cfg; uint32_t ahb_freq; uint32_t apb1_freq; @@ -91,10 +98,11 @@ static struct ClockConfig_t _clock_config[] = { {/* Performance Mode */ .type = RCC_PLL, .pll_src = RCC_HSE, //8MHz - .pllmul = RCC_CFGR_PLLMUL(9), //freq should noot exceed 72MHz + .pllmul = RCC_CFGR_PLLMUL(9), //freq should noot exceed 72MHz .hpre = RCC_CFGR_HPRE_DIV_NONE, - .ppre1 = RCC_CFGR_PPRE_DIV_2, //freq should not exceed 36MHz + .ppre1 = RCC_CFGR_PPRE_DIV_2, //freq should not exceed 36MHz .ppre2 = RCC_CFGR_PPRE_DIV_NONE, + .adcpre = RCC_CFGR_ADCPRE_DIV_6, //freq should not exceed 14MHz .flash_cfg = FLASH_ACR_LATENCY_2, .ahb_freq = 72000000, .apb1_freq = 36000000, @@ -106,6 +114,7 @@ static struct ClockConfig_t _clock_config[] = { .hpre = RCC_CFGR_HPRE_DIV_16, .ppre1 = RCC_CFGR_PPRE_DIV_16, .ppre2 = RCC_CFGR_PPRE_DIV_16, + .adcpre = RCC_CFGR_ADCPRE_DIV_2, .flash_cfg = FLASH_ACR_LATENCY_0, .ahb_freq = 500000, .apb1_freq = 500000, @@ -206,10 +215,11 @@ void rcc_config_clock(uint32_t config, Clock_t *sysclks) // AHB: AHBCLK > 25MHz // APB1: APB1CLK <= 36MHz // APB2: APB2CLK <= 72MHz - RCC->CFGR = ( RCC->CFGR & ~((0x3F<<8) | (0xF<<4)) ) | + RCC->CFGR = ( RCC->CFGR & ~((0x3F<<8) | (0xF<<4) | (0x3<<14)) ) | ((clk->hpre & 0xF) << 4) | ((clk->ppre1 & 0x7) << 8) | - ((clk->ppre2 & 0x7) << 11); + ((clk->ppre2 & 0x7) << 11)| + (clk->adcpre << 14); // configure PLL RCC->CFGR &= !(0xF<<18); @@ -241,7 +251,8 @@ void rcc_config_clock(uint32_t config, Clock_t *sysclks) sysclks->ahb_freq = clk->ahb_freq; sysclks->apb1_freq = clk->apb1_freq; sysclks->apb2_freq = clk->apb2_freq; - //TODO check timer frequencies - sysclks->apb1_timer_freq = clk->ppre1==RCC_CFGR_PPRE_DIV_NONE ? clk->apb1_freq : 2*clk->apb1_freq; - sysclks->apb2_timer_freq = clk->ppre2==RCC_CFGR_PPRE_DIV_NONE ? clk->apb2_freq : 2*clk->apb2_freq; + sysclks->apb1_timer_freq = + clk->ppre1==RCC_CFGR_PPRE_DIV_NONE ? clk->apb1_freq : 2*clk->apb1_freq; + sysclks->apb2_timer_freq = + clk->ppre2==RCC_CFGR_PPRE_DIV_NONE ? clk->apb2_freq : 2*clk->apb2_freq; } diff --git a/src/drivers/tags b/src/drivers/tags index eb79519..f27e006 100644 --- a/src/drivers/tags +++ b/src/drivers/tags @@ -5,6 +5,8 @@ !_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ !_TAG_PROGRAM_URL https://ctags.io/ /official site/ !_TAG_PROGRAM_VERSION 0.0.0 /3fdf28bc/ +ADC_Data adc.h /^} ADC_Data;$/;" t typeref:struct:__anon0f12ca630108 +ADC_H adc.h /^#define ADC_H$/;" d CLOCK_CONFIG_END rcc.h /^ CLOCK_CONFIG_END$/;" e enum:Clock_config CLOCK_CONFIG_PERFORMANCE rcc.h /^ CLOCK_CONFIG_PERFORMANCE,$/;" e enum:Clock_config CLOCK_CONFIG_POWERSAVE rcc.h /^ CLOCK_CONFIG_POWERSAVE,$/;" e enum:Clock_config @@ -49,6 +51,10 @@ PIN_7 io.h /^ PIN_7 = (1 << 7),$/;" e enum:io_pin PIN_8 io.h /^ PIN_8 = (1 << 8),$/;" e enum:io_pin PIN_9 io.h /^ PIN_9 = (1 << 9),$/;" e enum:io_pin PIN_ALL io.h /^ PIN_ALL = 0xFFFF$/;" e enum:io_pin +RCC_CFGR_ADCPRE_DIV_2 rcc.c /^#define RCC_CFGR_ADCPRE_DIV_2 /;" d file: +RCC_CFGR_ADCPRE_DIV_4 rcc.c /^#define RCC_CFGR_ADCPRE_DIV_4 /;" d file: +RCC_CFGR_ADCPRE_DIV_6 rcc.c /^#define RCC_CFGR_ADCPRE_DIV_6 /;" d file: +RCC_CFGR_ADCPRE_DIV_8 rcc.c /^#define RCC_CFGR_ADCPRE_DIV_8 /;" d file: RCC_CFGR_HPRE_DIV_128 rcc.c /^#define RCC_CFGR_HPRE_DIV_128 /;" d file: RCC_CFGR_HPRE_DIV_16 rcc.c /^#define RCC_CFGR_HPRE_DIV_16 /;" d file: RCC_CFGR_HPRE_DIV_256 rcc.c /^#define RCC_CFGR_HPRE_DIV_256 /;" d file: @@ -79,11 +85,15 @@ TIM1_UP_IRQHandler timer.c /^void TIM1_UP_IRQHandler(void) {$/;" f typeref:typen TIM2_IRQHandler timer.c /^void TIM2_IRQHandler(void) {$/;" f typeref:typename:void TIM3_IRQHandler timer.c /^void TIM3_IRQHandler(void) {$/;" f typeref:typename:void TIM4_IRQHandler timer.c /^void TIM4_IRQHandler(void) {$/;" f typeref:typename:void +TIMER_H timer.h /^#define TIMER_H$/;" d _Clock_t rcc.h /^typedef struct _Clock_t {$/;" s _IO_H_ io.h /^#define _IO_H_$/;" d _RCC_H_ rcc.h /^#define _RCC_H_$/;" d -_TIMER_H_ timer.h /^#define _TIMER_H_$/;" d +__anon0f12ca630108 adc.h /^typedef struct {$/;" s _clock_config rcc.c /^static struct ClockConfig_t _clock_config[] = {$/;" v typeref:struct:ClockConfig_t[] file: +adc_init adc.c /^int adc_init(ADC_TypeDef* adc) {$/;" f typeref:typename:int +adc_read adc.c /^int adc_read(void) {$/;" f typeref:typename:int +adcpre rcc.c /^ uint8_t adcpre;$/;" m struct:ClockConfig_t typeref:typename:uint8_t file: ahb_freq rcc.c /^ uint32_t ahb_freq;$/;" m struct:ClockConfig_t typeref:typename:uint32_t file: ahb_freq rcc.h /^ uint32_t ahb_freq;$/;" m struct:_Clock_t typeref:typename:uint32_t apb1_freq rcc.c /^ uint32_t apb1_freq;$/;" m struct:ClockConfig_t typeref:typename:uint32_t file: @@ -117,7 +127,7 @@ rcc_osc_off rcc.c /^static void rcc_osc_off(enum rcc_osc osc)$/;" f typeref:type rcc_osc_on rcc.c /^static void rcc_osc_on(enum rcc_osc osc)$/;" f typeref:typename:void file: rcc_osc rcc.c /^enum rcc_osc {$/;" g file: rcc_set_sysclk rcc.c /^static void rcc_set_sysclk(enum rcc_osc osc)$/;" f typeref:typename:void file: -timer_config_cb timer.c /^int timer_config_cb(TIM_TypeDef* tmr, OnTick cb) {$/;" f typeref:typename:int +timer_config_cb timer.c /^int timer_config_cb(TIM_TypeDef* tmr, uint32_t* clk, OnTick cb) {$/;" f typeref:typename:int timer_set_period timer.c /^int timer_set_period(TIM_TypeDef *tmr, uint16_t tick) {$/;" f typeref:typename:int timer_start timer.c /^void timer_start(TIM_TypeDef *tmr) {$/;" f typeref:typename:void timer_stop timer.c /^void timer_stop(TIM_TypeDef *tmr) {$/;" f typeref:typename:void diff --git a/src/drivers/timer.c b/src/drivers/timer.c index 5fc73d4..1c58586 100644 --- a/src/drivers/timer.c +++ b/src/drivers/timer.c @@ -263,8 +263,6 @@ void timer_start(TIM_TypeDef *tmr) { // enable counting tmr->CR1 |= 1; - - } void timer_stop(TIM_TypeDef *tmr) { diff --git a/src/drivers/timer.h b/src/drivers/timer.h index 24e5918..eb9b893 100644 --- a/src/drivers/timer.h +++ b/src/drivers/timer.h @@ -1,14 +1,10 @@ -#ifndef _TIMER_H_ -#define _TIMER_H_ +#ifndef TIMER_H +#define TIMER_H #include "../target/stm32f103xb.h" #include "../config.h" #include "rcc.h" -#ifdef __cplusplus -extern "C" { -#endif - typedef void (*OnTick)(void); //------------------------------------------------------------------------------ @@ -81,8 +77,5 @@ void timer_stop(TIM_TypeDef *tmr); // */ //#define pwm_stop(pwm) timer_stop(pwm) -#ifdef __cplusplus -} -#endif #endif diff --git a/src/main.c b/src/main.c index 881d620..5933cbb 100644 --- a/src/main.c +++ b/src/main.c @@ -1,11 +1,13 @@ #include "drivers/rcc.h" #include "drivers/io.h" +#include "drivers/adc.h" Clock_t sysclks; #include "drivers/timer.h" int val = 0; +uint16_t data = 0; static void timeout_cb(void) { io_write(GPIOC, val, PIN_13); @@ -20,12 +22,16 @@ int main(void) { return 0; io_write(GPIOC, 1, PIN_13); - //timer_tick_init(TIM2, 1000, timeout_cb); - //timer_start(TIM2); + timer_tick_init(TIM2, 1000, timeout_cb); + timer_start(TIM2); + + if(io_configure(GPIOA, PIN_4 | PIN_5, IO_MODE_INPUT | IO_IN_ANALOG, 0)) + return 0; + if(adc_init(ADC1)) return 0; for(;;){ - timer_wait_ms(TIM1, 500, 0); - timer_wait_ms(TIM2, 500, timeout_cb); + data = adc_read(ADC1, 5); + data -= adc_read(ADC1, 4); } return 0;