Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STM32F0 ADC Support #132

Merged
merged 2 commits into from
Nov 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions examples/nucleo_f042k6/adc/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016-2017, Niklas Hauser
* Copyright (c) 2017, Nick Sarten
* Copyright (c) 2018, Carl Treudler
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <modm/board.hpp>

using namespace Board;

typedef GpioInputA0 AdcIn1;

int
main()
{
Board::initialize();
LedD13::setOutput();

Adc::connect<AdcIn1::In0>();
Adc::initialize(Adc::ClockMode::PCLKDividedBy4, Adc::CalibrationMode::DoNotCalibrate);

while (1)
{
LedD13::toggle();
modm::delayMilliseconds(250);

Adc::setPinChannel<AdcIn1>();
Adc::startConversion();
while(!Adc::isConversionFinished()) { }
MODM_LOG_INFO << "ADC A0: " << Adc::getValue() << modm::endl;

}

return 0;
}
10 changes: 10 additions & 0 deletions examples/nucleo_f042k6/adc/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<library>
<extends>modm:board:nucleo-f042k6</extends>
<options>
<option name=":build:build.path">../../../build/nucleo_f042k6/adc</option>
</options>
<modules>
<module>:build:scons</module>
<module>:platform:adc</module>
</modules>
</library>
29 changes: 18 additions & 11 deletions src/modm/platform/adc/stm32f0/adc.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/*
* Copyright (c) 2018, Niklas Hauser
* Copyright (c) 2018, Álan Crístoffer
* Copyright (c) 2018, Carl Treudler
*
* This file is part of the modm project.
*
Expand All @@ -15,14 +16,13 @@
#define MODM_STM32F0_ADC_HPP

#include <stdint.h>
#include "../../../type_ids.hpp"
#include "../../../device.hpp"
#include "../device.hpp"
#include <modm/architecture/interface/register.hpp>

#include <modm/platform/gpio/connector.hpp>

namespace modm
{
namespace stm32
namespace platform
{
/**
* Analog/Digital-Converter module (ADC1).
Expand All @@ -46,15 +46,11 @@ public:
* This code was generated using the family datasheet, but not all devices in the
* family have 16 channels.
*/
%% for channel in range(0,16)
/// TypeId used to connect GPIO pins to this adc's Channel{{ channel }}.
static const TypeId::AdcChannel{{ channel }} Channel{{ channel }};
%% endfor

/// Channels, which can be used with this ADC.
enum class Channel : uint8_t
{
%% for channel in range(0,16)
%% for channel in channels
Channel{{ channel }} = {{ channel }},
%% endfor
%#
Expand Down Expand Up @@ -123,6 +119,17 @@ public:
};
MODM_FLAGS32(InterruptFlag);

public:
// start inherited documentation
template< template<Peripheral _> class... Signals >
static void
connect()
{
using Connector = GpioConnector<Peripheral::Adc, Signals...>;
Connector::connect();
}


/**
* Initialize and enable the A/D converter.
*
Expand Down Expand Up @@ -205,8 +212,8 @@ public:
static inline constexpr Channel
getPinChannel()
{
constexpr int8_t channel{Gpio::template AdcChannel<Peripheral::Adc{{ id }}>};
static_assert(channel >= 0, "Adc{{id}} does not have a channel for this pin!");
constexpr int8_t channel{Gpio::template AdcChannel<Peripheral::Adc>};
static_assert(channel >= 0, "Adc does not have a channel for this pin!");
return Channel(channel);
}

Expand Down
43 changes: 21 additions & 22 deletions src/modm/platform/adc/stm32f0/adc_impl.hpp.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// coding: utf-8
/*
* Copyright (c) 2018, Álan Crístoffer
* Copyright (c) 2018, Carl Treudler
*
* This file is part of the modm project.
*
Expand All @@ -11,13 +12,11 @@
// ----------------------------------------------------------------------------

#ifndef MODM_STM32F0_ADC_HPP
# error "Don't include this file directly, use 'adc_{{ id }}.hpp' instead!"
# error "Don't include this file directly, use 'adc.hpp' instead!"
#endif

#include <modm/architecture/driver/delay.hpp> // modm::delayMicroseconds

uint16_t
modm::stm32::Adc::initialize(const ClockMode clk,
modm::platform::Adc::initialize(const ClockMode clk,
const CalibrationMode cal)
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
Expand All @@ -31,7 +30,7 @@ modm::stm32::Adc::initialize(const ClockMode clk,
ADC1->CFGR2 |= static_cast<uint32_t>(clk);
}

uint16_t calibrationResult = modm::stm32::Adc::calibrate(cal);
uint16_t calibrationResult = modm::platform::Adc::calibrate(cal);

ADC1->ISR |= ADC_ISR_ADRDY; // ISR is cleared by setting 1 to the bit
ADC1->CR |= ADC_CR_ADEN;
Expand All @@ -43,15 +42,15 @@ modm::stm32::Adc::initialize(const ClockMode clk,
}

void
modm::stm32::Adc::disable(const bool blocking)
modm::platform::Adc::disable(const bool blocking)
{
ADC1->CR |= ADC_CR_ADDIS;
while ( blocking && (ADC1->CR & ADC_CR_ADEN) != 0 )
;
}

void
modm::stm32::Adc::setAutoOffMode(const bool enable)
modm::platform::Adc::setAutoOffMode(const bool enable)
{
if (enable) {
ADC1->CFGR1 |= ADC_CFGR1_AUTOFF;
Expand All @@ -61,13 +60,13 @@ modm::stm32::Adc::setAutoOffMode(const bool enable)
}

bool
modm::stm32::Adc::isReady()
modm::platform::Adc::isReady()
{
return static_cast<bool>(getInterruptFlags() & InterruptFlag::Ready);
}

uint16_t
modm::stm32::Adc::calibrate(const CalibrationMode mode)
modm::platform::Adc::calibrate(const CalibrationMode mode)
{
if (mode != CalibrationMode::DoNotCalibrate) {
if ( (ADC1->CR & ADC_CR_ADEN) != 0 ) {
Expand All @@ -89,7 +88,7 @@ modm::stm32::Adc::calibrate(const CalibrationMode mode)
}

void
modm::stm32::Adc::setDataAlignmentAndResolution(const DataAlignment align,
modm::platform::Adc::setDataAlignmentAndResolution(const DataAlignment align,
const Resolution res)
{
ADC1->CFGR1 = static_cast<uint32_t>(align) |
Expand All @@ -98,7 +97,7 @@ modm::stm32::Adc::setDataAlignmentAndResolution(const DataAlignment align,
}

bool
modm::stm32::Adc::setChannel(const Channel channel,
modm::platform::Adc::setChannel(const Channel channel,
const SampleTime sampleTime)
{
if(static_cast<uint32_t>(channel) > 18) {
Expand All @@ -118,7 +117,7 @@ modm::stm32::Adc::setChannel(const Channel channel,
}

void
modm::stm32::Adc::clearChannel(const Channel channel)
modm::platform::Adc::clearChannel(const Channel channel)
{
ADC1->CHSELR &= ~(1 << static_cast<uint32_t>(channel));
if (channel == Channel::InternalReference) {
Expand All @@ -129,7 +128,7 @@ modm::stm32::Adc::clearChannel(const Channel channel)
}

void
modm::stm32::Adc::setFreeRunningMode(const bool enable)
modm::platform::Adc::setFreeRunningMode(const bool enable)
{
if (enable) {
ADC1->CFGR1 |= ADC_CFGR1_CONT;
Expand All @@ -139,7 +138,7 @@ modm::stm32::Adc::setFreeRunningMode(const bool enable)
}

void
modm::stm32::Adc::startConversion(void)
modm::platform::Adc::startConversion(void)
{
acknowledgeInterruptFlag(InterruptFlag::EndOfConversion |
InterruptFlag::EndOfSampling |
Expand All @@ -151,13 +150,13 @@ modm::stm32::Adc::startConversion(void)
}

bool
modm::stm32::Adc::isConversionFinished(void)
modm::platform::Adc::isConversionFinished(void)
{
return static_cast<bool>(getInterruptFlags() & InterruptFlag::EndOfSampling);
}

void
modm::stm32::Adc::enableInterruptVector(const uint32_t priority,
modm::platform::Adc::enableInterruptVector(const uint32_t priority,
const bool enable)
{
if (enable) {
Expand All @@ -169,33 +168,33 @@ modm::stm32::Adc::enableInterruptVector(const uint32_t priority,
}

void
modm::stm32::Adc::enableInterrupt(const Interrupt_t interrupt)
modm::platform::Adc::enableInterrupt(const Interrupt_t interrupt)
{
ADC1->IER |= interrupt.value;
}

void
modm::stm32::Adc::disableInterrupt(const Interrupt_t interrupt)
modm::platform::Adc::disableInterrupt(const Interrupt_t interrupt)
{
ADC1->IER &= ~interrupt.value;
}

modm::stm32::Adc::InterruptFlag_t
modm::stm32::Adc::getInterruptFlags()
modm::platform::Adc::InterruptFlag_t
modm::platform::Adc::getInterruptFlags()
{
return InterruptFlag_t(ADC1->ISR);
}

void
modm::stm32::Adc::acknowledgeInterruptFlag(const InterruptFlag_t flags)
modm::platform::Adc::acknowledgeInterruptFlag(const InterruptFlag_t flags)
{
// Flags are cleared by writing a one to the flag position.
// Writing a zero is ignored.
ADC1->ISR = flags.value;
}

void
modm::stm32::Adc::setWaitMode(const bool enable)
modm::platform::Adc::setWaitMode(const bool enable)
{
if (enable) {
ADC1->CFGR1 |= ADC_CFGR1_WAIT;
Expand Down
47 changes: 47 additions & 0 deletions src/modm/platform/adc/stm32f0/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016-2018, Niklas Hauser
# Copyright (c) 2017, Fabian Greif
# Copyright (c) 2018, Carl Treudler
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

def init(module):
module.name = "adc"
module.parent = "platform"
module.description = "Analog-to-Digital Converter (ADC)"

def prepare(module, options):
device = options[":target"]
if not device.has_driver("adc:stm32-f0"):
return False
module.depends(
":architecture:delay",
":architecture:register",
":cmsis:device",
":platform:gpio")
return True

def build(env):
device = env[":target"]
driver = device.get_driver("adc")

properties = device.properties
properties["target"] = device.identifier
properties["driver"] = driver
#properties["id"] = 1

channels = range(0,16)
properties["channels"] = sorted(channels)

env.substitutions = properties
env.outbasepath = "modm/src/modm/platform/adc"

env.template("adc.hpp.in", "adc.hpp")
env.template("adc_impl.hpp.in", "adc_impl.hpp")
1 change: 1 addition & 0 deletions src/modm/platform/gpio/stm32/pin.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Gpio{{ port ~ pin }} : public Gpio, public ::modm::GpioIO
template<class... Gpios>
friend class GpioSet;
using PinSet = GpioSet<Gpio{{ port ~ pin }}>;
friend class Adc;
friend class Adc1; friend class Adc2;
friend class Adc3; friend class Adc4;
public:
Expand Down