Merging pull request #72 Doc
Merge remote-tracking branch 'ksarkies/doc' Conflicts: doc/stm32f1/Doxyfile doc/stm32f2/Doxyfile doc/stm32f4/Doxyfile lib/stm32/f1/Makefile lib/stm32/f2/Makefile lib/stm32/f4/Makefile
This commit is contained in:
82
lib/stm32/common/crc_common_all.c
Normal file
82
lib/stm32/common/crc_common_all.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/** @addtogroup crc_file
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Karl Palsson <karlp@remake.is>
|
||||
|
||||
@date 15 October 2012
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@remake.is>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/crc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief CRC Reset.
|
||||
|
||||
Reset the CRC unit and forces the data register to all 1s.
|
||||
|
||||
*/
|
||||
|
||||
void crc_reset(void)
|
||||
{
|
||||
CRC_CR |= CRC_CR_RESET;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief CRC Calculate.
|
||||
|
||||
Writes a data word to the register, the write operation stalling until the
|
||||
computation is complete.
|
||||
|
||||
@param[in] data Unsigned int32.
|
||||
@returns int32 Computed CRC result
|
||||
*/
|
||||
|
||||
u32 crc_calculate(u32 data)
|
||||
{
|
||||
CRC_DR = data;
|
||||
// Data sheet says this blocks until it's ready....
|
||||
return CRC_DR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief CRC Calculate of a Block of Data.
|
||||
|
||||
Writes data words consecutively to the register, the write operation stalling
|
||||
until the computation of each word is complete.
|
||||
|
||||
@param[in] datap Unsigned int32. pointer to an array of 32 bit data words.
|
||||
@returns int32 Final computed CRC result
|
||||
*/
|
||||
|
||||
u32 crc_calculate_block(u32 *datap, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
CRC_DR = datap[i];
|
||||
}
|
||||
return CRC_DR;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
516
lib/stm32/common/dac_common_all.c
Normal file
516
lib/stm32/common/dac_common_all.c
Normal file
@@ -0,0 +1,516 @@
|
||||
/** @addtogroup dac_file
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the Digital to Analog Conversion System in the
|
||||
STM32F series of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
The DAC is present only in a limited set of devices, notably some
|
||||
of the connection line, high density and XL devices.
|
||||
|
||||
Two DAC channels are available, however unlike the ADC channels these
|
||||
are separate DAC devices controlled by the same register block.
|
||||
|
||||
The DAC is on APB1. Its clock must be enabled in RCC and the GPIO
|
||||
ports set to alternate function output before it can be used.
|
||||
The digital output driver is disabled so the output driver mode
|
||||
(push-pull/open drain) is arbitrary.
|
||||
|
||||
The DAC has a holding (buffer) register and an output register from
|
||||
which the analog output is derived. The holding register must be
|
||||
loaded first. If triggering is enabled the output register is loaded
|
||||
from the holding register after a trigger occurs. If triggering is
|
||||
not enabled the holding register contents are transferred directly
|
||||
to the output register.
|
||||
|
||||
@note To avoid nonlinearities, do not allow outputs to range close
|
||||
to zero or V_analog.
|
||||
|
||||
@section dac_api_dual Dual Channel Conversion
|
||||
|
||||
There are dual modes in which both DACs are used to output data
|
||||
simultaneously or independently on both channels. The data must be
|
||||
presented according to the formats described in the datasheets. A
|
||||
convenience function @ref dac_load_data_buffer_dual is provided
|
||||
for software controlled use.
|
||||
|
||||
A variety of modes are available depending on whether independent
|
||||
or simultaneous output is desired, and whether waveforms are to be
|
||||
superimposed. Refer to the datasheets.
|
||||
|
||||
If DMA is used, only enable it for one of the channels. The DMA
|
||||
requests will then serve data in dual format to the data register
|
||||
dedicated to dual mode. The data will then be split and loaded to the
|
||||
appropriate DAC following the next trigger. There are three registers
|
||||
available, one for each of the formats: 12 bit right-aligned, 12 bit
|
||||
left-aligned and 8 bit right-aligned. The desired format is determined
|
||||
by specifying the appropriate register to the DMA controller.
|
||||
|
||||
@section dac_api_basic_ex Basic DAC handling API.
|
||||
|
||||
Set the DAC's GPIO port to any alternate function output mode. Enable the
|
||||
DAC clock. Enable the DAC, set a trigger source and load the buffer
|
||||
with the first value. After the DAC is triggered, load the buffer with
|
||||
the next value. This example uses software triggering and added noise.
|
||||
The trigger and further buffer load calls are made when data is to be
|
||||
sent out.
|
||||
|
||||
@code
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4);
|
||||
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_DACEN);
|
||||
dac_disable(CHANNEL_1);
|
||||
dac_set_waveform_characteristics(DAC_CR_MAMP1_8);
|
||||
dac_set_waveform_generation(DAC_CR_WAVE1_NOISE);
|
||||
dac_enable(CHANNEL_1);
|
||||
dac_set_trigger_source(DAC_CR_TSEL1_SW);
|
||||
dac_load_data_buffer_single(0, RIGHT12, CHANNEL_1);
|
||||
....
|
||||
dac_software_trigger(CHANNEL_1);
|
||||
dac_load_data_buffer_single(value, RIGHT12, CHANNEL_1);
|
||||
@endcode
|
||||
|
||||
@section dac_api_dma_ex Simultaneous Dual DAC with DMA.
|
||||
|
||||
This example in part sets up the DAC channel 1 DMA (DMA2 channel 3) to read
|
||||
16 bit data from memory into the right-aligned 8 bit dual register DAC_DHR8RD.
|
||||
Both DAC channels are enabled, and both triggers are set to the same timer
|
||||
2 input as required for simultaneous operation. DMA is enabled for DAC channel
|
||||
1 only to ensure that only one DMA request is generated.
|
||||
|
||||
@code
|
||||
dma_set_memory_size(DMA2,DMA_CHANNEL3,DMA_CCR_MSIZE_16BIT);
|
||||
dma_set_peripheral_size(DMA2,DMA_CHANNEL3,DMA_CCR_PSIZE_16BIT);
|
||||
dma_set_read_from_memory(DMA2,DMA_CHANNEL3);
|
||||
dma_set_peripheral_address(DMA2,DMA_CHANNEL3,(u32) &DAC_DHR8RD);
|
||||
dma_enable_channel(DMA2,DMA_CHANNEL3);
|
||||
...
|
||||
dac_trigger_enable(CHANNEL_D);
|
||||
dac_set_trigger_source(DAC_CR_TSEL1_T2 | DAC_CR_TSEL2_T2);
|
||||
dac_dma_enable(CHANNEL_1);
|
||||
dac_enable(CHANNEL_D);
|
||||
@endcode
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Ken Sarkies
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/dac.h>
|
||||
|
||||
#define MASK8 0xFF
|
||||
#define MASK12 0xFFF
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Enable.
|
||||
|
||||
Enable a digital to analog converter channel. After setting this enable, the DAC
|
||||
requires a t<sub>wakeup</sub> time typically around 10 microseconds before it
|
||||
actually wakes up.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_EN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_EN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_EN1 | DAC_CR_EN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Disable.
|
||||
|
||||
Disable a digital to analog converter channel.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_EN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_EN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_EN1 | DAC_CR_EN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Output Buffer Enable.
|
||||
|
||||
Enable a digital to analog converter channel output drive buffer. This is an optional
|
||||
amplifying buffer that provides additional drive for the output signal. The
|
||||
buffer is enabled by default after a reset and needs to be explicitly disabled
|
||||
if required.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_buffer_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_BOFF1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_BOFF2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_BOFF1 | DAC_CR_BOFF2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Output Buffer Disable.
|
||||
|
||||
Disable a digital to analog converter channel output drive buffer. Disabling this will
|
||||
reduce power consumption slightly and will increase the output impedance of the DAC.
|
||||
The buffers are enabled by default after a reset.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_buffer_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_BOFF1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_BOFF2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_BOFF1 | DAC_CR_BOFF2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel DMA Enable.
|
||||
|
||||
Enable a digital to analog converter channel DMA mode (connected to DMA2 channel
|
||||
3 for DAC channel 1 and DMA2 channel 4 for DAC channel 2). A DMA request is
|
||||
generated following an external trigger.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_dma_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_DMAEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_DMAEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel DMA Disable.
|
||||
|
||||
Disable a digital to analog converter channel DMA mode.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_dma_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_DMAEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_DMAEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Trigger Enable.
|
||||
|
||||
Enable a digital to analog converter channel external trigger mode. This allows an
|
||||
external trigger to initiate register transfers from the buffer register to the DAC
|
||||
output register, followed by a DMA transfer to the buffer register if DMA is enabled.
|
||||
The trigger source must also be selected.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_trigger_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_TEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_TEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_TEN1 | DAC_CR_TEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Trigger Disable.
|
||||
|
||||
Disable a digital to analog converter channel external trigger.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_trigger_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_TEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_TEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_TEN1 | DAC_CR_TEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Set DAC Channel Trigger Source.
|
||||
|
||||
Sets the digital to analog converter trigger source, which can be taken from various
|
||||
timers, an external trigger or a software trigger.
|
||||
|
||||
@param[in] dac_trig_src u32. Taken from @ref dac_trig2_sel or @ref dac_trig1_sel or
|
||||
a logical OR of one of each of these to set both channels simultaneously.
|
||||
*/
|
||||
|
||||
void dac_set_trigger_source(u32 dac_trig_src)
|
||||
{
|
||||
DAC_CR |= dac_trig_src;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Enable and Set DAC Channel Waveform Generation.
|
||||
|
||||
Enable the digital to analog converter waveform generation as either pseudo-random
|
||||
noise or triangular wave. These signals are superimposed on existing output values
|
||||
in the DAC output registers.
|
||||
|
||||
@note The DAC trigger must be enabled for this to work.
|
||||
|
||||
@param[in] dac_wave_ens u32. Taken from @ref dac_wave1_en or @ref dac_wave2_en or
|
||||
a logical OR of one of each of these to set both channels simultaneously.
|
||||
*/
|
||||
|
||||
void dac_set_waveform_generation(u32 dac_wave_ens)
|
||||
{
|
||||
DAC_CR |= dac_wave_ens;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Disable DAC Channel Waveform Generation.
|
||||
|
||||
Disable a digital to analog converter channel superimposed waveform generation.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_disable_waveform_generation(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_WAVE1_DIS;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_WAVE2_DIS;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_WAVE1_DIS | DAC_CR_WAVE2_DIS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Set DAC Channel LFSR Mask or Triangle Wave Amplitude.
|
||||
|
||||
Sets the digital to analog converter superimposed waveform generation characteristics.
|
||||
@li If the noise generation mode is set, this sets the length of the PRBS sequence and
|
||||
hence the amplitude of the output noise signal. Default setting is length 1.
|
||||
@li If the triangle wave generation mode is set, this sets the amplitude of the
|
||||
output signal as 2^(n)-1 where n is the parameter value. Default setting is 1.
|
||||
|
||||
@note High amplitude levels of these waveforms can overload the DAC and distort the
|
||||
signal output.
|
||||
@note This must be called before enabling the DAC as the settings will then become read-only.
|
||||
@note The DAC trigger must be enabled for this to work.
|
||||
|
||||
@param[in] dac_mamp u32. Taken from @ref dac_mamp2 or @ref dac_mamp1 or a logical OR
|
||||
of one of each of these to set both channels simultaneously.
|
||||
*/
|
||||
|
||||
void dac_set_waveform_characteristics(u32 dac_mamp)
|
||||
{
|
||||
DAC_CR |= dac_mamp;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Load DAC Data Register.
|
||||
|
||||
Loads the appropriate digital to analog converter data register with 12 or 8 bit
|
||||
data to be converted on a channel. The data can be aligned as follows:
|
||||
@li right-aligned 8 bit data in bits 0-7
|
||||
@li right-aligned 12 bit data in bits 0-11
|
||||
@li left aligned 12 bit data in bits 4-15
|
||||
|
||||
This function can also be used to load the dual channel registers if the data is
|
||||
formatted according to the datasheets:
|
||||
@li right-aligned 8 bit data in bits 0-7 for channel 1 and 8-15 for channel 2
|
||||
@li right-aligned 12 bit data in bits 0-11 for channel 1 and 16-27 for channel 2
|
||||
@li left aligned 12 bit data in bits 4-15 for channel 1 and 20-31 for channel 2
|
||||
|
||||
@param[in] dac_data u32 with appropriate alignment.
|
||||
@param[in] dac_data_format enum ::data_align. Alignment and size.
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_load_data_buffer_single(u32 dac_data, data_align dac_data_format, data_channel dac_channel)
|
||||
{
|
||||
if (dac_channel == CHANNEL_1)
|
||||
{
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8R1 = dac_data;
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12R1 = dac_data;
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12L1 = dac_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (dac_channel == CHANNEL_2)
|
||||
{
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8R2 = dac_data;
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12R2 = dac_data;
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12L2 = dac_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8RD = dac_data;
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12RD = dac_data;
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12LD = dac_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Load DAC Dual Data Register.
|
||||
|
||||
Loads the appropriate digital to analog converter dual data register with 12 or
|
||||
8 bit data to be converted for both channels. This allows high bandwidth
|
||||
simultaneous or independent analog output. The data in both channels are aligned
|
||||
identically.
|
||||
|
||||
@param[in] dac_data1 u32 for channel 1 with appropriate alignment.
|
||||
@param[in] dac_data2 u32 for channel 2 with appropriate alignment.
|
||||
@param[in] dac_data_format enum ::data_align. Right or left aligned, and 8 or 12 bit.
|
||||
*/
|
||||
|
||||
void dac_load_data_buffer_dual(u32 dac_data1, u32 dac_data2, data_align dac_data_format)
|
||||
{
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8RD = ((dac_data1 & MASK8) | ((dac_data2 & MASK8) << 8));
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12RD = ((dac_data1 & MASK12) | ((dac_data2 & MASK12) << 12));
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12LD = ((dac_data1 & MASK12) | ((dac_data2 & MASK12) << 16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Trigger the DAC by a Software Trigger.
|
||||
|
||||
If the trigger source is set to be a software trigger, cause a trigger to occur.
|
||||
The trigger is cleared by hardware after conversion.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_software_trigger(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_SWTRIGR |= (DAC_SWTRIGR_SWTRIG1 | DAC_SWTRIGR_SWTRIG2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
411
lib/stm32/common/i2c_common_all.c
Normal file
411
lib/stm32/common/i2c_common_all.c
Normal file
@@ -0,0 +1,411 @@
|
||||
/** @addtogroup i2c_file
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
|
||||
|
||||
@date 15 October 2012
|
||||
|
||||
Devices can have up to two I2C peripherals. The peripherals support SMBus and
|
||||
PMBus variants.
|
||||
|
||||
A peripheral begins after reset in Slave mode. To become a Master a start
|
||||
condition must be generated. The peripheral will remain in Master mode unless
|
||||
a multimaster contention is lost or a stop condition is generated.
|
||||
|
||||
@todo all sorts of lovely stuff like DMA, Interrupts, SMBus variant, Status
|
||||
register access, Error conditions
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/i2c.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Reset.
|
||||
|
||||
The I2C peripheral and all its associated configuration registers are placed in the
|
||||
reset condition. The reset is effected via the RCC peripheral reset system.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_reset(u32 i2c)
|
||||
{
|
||||
switch (i2c) {
|
||||
case I2C1:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
|
||||
break;
|
||||
case I2C2:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Peripheral Enable.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_peripheral_enable(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) |= I2C_CR1_PE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Peripheral Disable.
|
||||
|
||||
This must not be reset while in Master mode until a communication has finished.
|
||||
In Slave mode, the peripheral is disabled only after communication has ended.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_peripheral_disable(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) &= ~I2C_CR1_PE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Send Start Condition.
|
||||
|
||||
If in Master mode this will cause a restart condition to occur at the end of the
|
||||
current transmission. If in Slave mode, this will initiate a start condition
|
||||
when the current bus activity is completed.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_send_start(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) |= I2C_CR1_START;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Send Stop Condition.
|
||||
|
||||
After the current byte transfer this will initiate a stop condition if in Master
|
||||
mode, or simply release the bus if in Slave mode.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_send_stop(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) |= I2C_CR1_STOP;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Clear Stop Flag.
|
||||
|
||||
Clear the "Send Stop" flag in the I2C config register
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_clear_stop(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) &= ~I2C_CR1_STOP;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
|
||||
|
||||
This sets an address for Slave mode operation, in 7 bit form.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] slave Unsigned int8. Slave address 0...127.
|
||||
*/
|
||||
|
||||
void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave)
|
||||
{
|
||||
I2C_OAR1(i2c) = (u16)(slave << 1);
|
||||
I2C_OAR1(i2c) &= ~I2C_OAR1_ADDMODE;
|
||||
I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set the 10 bit Slave Address for the Peripheral.
|
||||
|
||||
This sets an address for Slave mode operation, in 10 bit form.
|
||||
|
||||
@todo add "I2C_OAR1(i2c) |= (1 << 14);" as above
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] slave Unsigned int16. Slave address 0...1023.
|
||||
*/
|
||||
|
||||
void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave)
|
||||
{
|
||||
I2C_OAR1(i2c) = (u16)(I2C_OAR1_ADDMODE | slave);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set Fast Mode.
|
||||
|
||||
Set the clock frequency to the high clock rate mode (up to 400kHz). The actual
|
||||
clock frequency must be set with @ref i2c_set_clock_frequency
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_set_fast_mode(u32 i2c)
|
||||
{
|
||||
I2C_CCR(i2c) |= I2C_CCR_FS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set Standard Mode.
|
||||
|
||||
Set the clock frequency to the standard clock rate mode (up to 100kHz). The actual
|
||||
clock frequency must be set with @ref i2c_set_clock_frequency
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
|
||||
void i2c_set_standard_mode(u32 i2c)
|
||||
{
|
||||
I2C_CCR(i2c) &= ~I2C_CCR_FS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set Peripheral Clock Frequency.
|
||||
|
||||
Set the peripheral clock frequency: 2MHz to 36MHz (the APB frequency). Note that
|
||||
this is <b> not </b> the I2C bus clock. This is set in conjunction with the Clock
|
||||
Control register to generate the Master bus clock, see @ref i2c_set_ccr
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] freq Unsigned int8. Clock Frequency Setting @ref i2c_clock.
|
||||
*/
|
||||
|
||||
void i2c_set_clock_frequency(u32 i2c, u8 freq)
|
||||
{
|
||||
u16 reg16;
|
||||
reg16 = I2C_CR2(i2c) & 0xffc0; /* Clear bits [5:0]. */
|
||||
reg16 |= freq;
|
||||
I2C_CR2(i2c) = reg16;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set Bus Clock Frequency.
|
||||
|
||||
Set the bus clock frequency. This is a 12 bit number (0...4095) calculated
|
||||
from the formulae given in the STM32F1 reference manual in the description
|
||||
of the CCR field. It is a divisor of the peripheral clock frequency
|
||||
@ref i2c_set_clock_frequency modified by the fast mode setting
|
||||
@ref i2c_set_fast_mode
|
||||
|
||||
@todo provide additional API assitance to set the clock, eg macros
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] freq Unsigned int16. Bus Clock Frequency Setting 0...4095.
|
||||
*/
|
||||
|
||||
void i2c_set_ccr(u32 i2c, u16 freq)
|
||||
{
|
||||
u16 reg16;
|
||||
reg16 = I2C_CCR(i2c) & 0xf000; /* Clear bits [11:0]. */
|
||||
reg16 |= freq;
|
||||
I2C_CCR(i2c) = reg16;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set the Rise Time.
|
||||
|
||||
Set the maximum rise time on the bus according to the I2C specification, as 1
|
||||
more than the specified rise time in peripheral clock cycles. This is a 6 bit
|
||||
number.
|
||||
|
||||
@todo provide additional APIP assistance.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] trise Unsigned int16. Rise Time Setting 0...63.
|
||||
*/
|
||||
|
||||
void i2c_set_trise(u32 i2c, u16 trise)
|
||||
{
|
||||
I2C_TRISE(i2c) = trise;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Send the 7-bit Slave Address.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] slave Unsigned int16. Slave address 0...1023.
|
||||
@param[in] readwrite Unsigned int8. Single bit to instruct slave to receive or send @ref i2c_rw.
|
||||
*/
|
||||
|
||||
void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite)
|
||||
{
|
||||
I2C_DR(i2c) = (u8)((slave << 1) | readwrite);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Send Data.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] data Unsigned int8. Byte to send.
|
||||
*/
|
||||
|
||||
void i2c_send_data(u32 i2c, u8 data)
|
||||
{
|
||||
I2C_DR(i2c) = data;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Get Data.
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
uint8_t i2c_get_data(u32 i2c)
|
||||
{
|
||||
return I2C_DR(i2c) & 0xff;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Enable Interrupt
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] interrupt Unsigned int32. Interrupt to enable.
|
||||
*/
|
||||
void i2c_enable_interrupt(u32 i2c, u32 interrupt)
|
||||
{
|
||||
I2C_CR2(i2c) |= interrupt;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Disable Interrupt
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] interrupt Unsigned int32. Interrupt to disable.
|
||||
*/
|
||||
void i2c_disable_interrupt(u32 i2c, u32 interrupt)
|
||||
{
|
||||
I2C_CR2(i2c) &= ~interrupt;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Enable ACK
|
||||
|
||||
Enables acking of own 7/10 bit address
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_enable_ack(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) |= I2C_CR1_ACK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Disable ACK
|
||||
|
||||
Disables acking of own 7/10 bit address
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_disable_ack(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) &= ~I2C_CR1_ACK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C NACK Next Byte
|
||||
|
||||
Causes the I2C controller to NACK the reception of the next byte
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_nack_next(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) |= I2C_CR1_POS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C NACK Next Byte
|
||||
|
||||
Causes the I2C controller to NACK the reception of the current byte
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_nack_current(u32 i2c)
|
||||
{
|
||||
I2C_CR1(i2c) &= ~I2C_CR1_POS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set clock duty cycle
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
@param[in] dutycycle Unsigned int32. I2C duty cycle @ref i2c_duty_cycle.
|
||||
*/
|
||||
void i2c_set_dutycycle(u32 i2c, u32 dutycycle)
|
||||
{
|
||||
if (dutycycle == I2C_CCR_DUTY_DIV2)
|
||||
I2C_CCR(i2c) &= ~I2C_CCR_DUTY;
|
||||
else
|
||||
I2C_CCR(i2c) |= I2C_CCR_DUTY;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Enable DMA
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_enable_dma(u32 i2c)
|
||||
{
|
||||
I2C_CR2(i2c) |= I2C_CR2_DMAEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Disable DMA
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_disable_dma(u32 i2c)
|
||||
{
|
||||
I2C_CR2(i2c) &= ~I2C_CR2_DMAEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Set DMA last transfer
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_set_dma_last_transfer(u32 i2c)
|
||||
{
|
||||
I2C_CR2(i2c) |= I2C_CR2_LAST;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief I2C Clear DMA last transfer
|
||||
|
||||
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
|
||||
*/
|
||||
void i2c_clear_dma_last_transfer(u32 i2c)
|
||||
{
|
||||
I2C_CR2(i2c) &= ~I2C_CR2_LAST;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
140
lib/stm32/common/iwdg_common_all.c
Normal file
140
lib/stm32/common/iwdg_common_all.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/** @addtogroup iwdg_file
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies ksarkies@internode.on.net
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the Independent Watchdog Timer System in the STM32F1xx
|
||||
series of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
The watchdog timer uses the LSI (low speed internal) clock which is low power
|
||||
and continues to operate during stop and standby modes. Its frequency is
|
||||
nominally 32kHz (40kHz for the STM32F1xx series) but can vary from as low
|
||||
as 17kHz up to 60kHz (refer to datasheet electrical characteristics).
|
||||
|
||||
Note that the User Configuration option byte provides a means of automatically
|
||||
enabling the IWDG timer at power on (with counter value 0xFFF). If the
|
||||
relevant bit is not set, the IWDG timer must be enabled by software.
|
||||
|
||||
@note: Tested: CPU STM32F103RET6, Board ET-ARM Stamp STM32
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/iwdg.h>
|
||||
|
||||
#define LSI_FREQUENCY 32000
|
||||
#define COUNT_LENGTH 12
|
||||
#define COUNT_MASK ((1 << COUNT_LENGTH)-1)
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Enable Watchdog Timer
|
||||
|
||||
The watchdog timer is started. The timeout period defaults to 512 milliseconds
|
||||
unless it has been previously defined.
|
||||
|
||||
*/
|
||||
|
||||
void iwdg_start(void)
|
||||
{
|
||||
IWDG_KR = IWDG_KR_START;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Set Period in Milliseconds
|
||||
|
||||
The countdown period is converted into count and prescale values. The maximum
|
||||
period is 32.76 seconds; values above this are truncated. Periods less than 1ms
|
||||
are not supported by this library.
|
||||
|
||||
A delay of up to 5 clock cycles of the LSI clock (about 156 microseconds)
|
||||
can occasionally occur if the prescale or preload registers are currently busy
|
||||
loading a previous value.
|
||||
|
||||
@param[in] period u32 Period in milliseconds (< 32760) from a watchdog reset until
|
||||
a system reset is issued.
|
||||
*/
|
||||
|
||||
void iwdg_set_period_ms(u32 period)
|
||||
{
|
||||
u32 count, prescale, reload, exponent;
|
||||
/* Set the count to represent ticks of the 32kHz LSI clock */
|
||||
count = (period << 5);
|
||||
/* Strip off the first 12 bits to get the prescale value required */
|
||||
prescale = (count >> 12);
|
||||
if (prescale > 256) {exponent = IWDG_PR_DIV256; reload = COUNT_MASK;}
|
||||
else if (prescale > 128) {exponent = IWDG_PR_DIV256; reload = (count >> 8);}
|
||||
else if (prescale > 64) {exponent = IWDG_PR_DIV128; reload = (count >> 7);}
|
||||
else if (prescale > 32) {exponent = IWDG_PR_DIV64; reload = (count >> 6);}
|
||||
else if (prescale > 16) {exponent = IWDG_PR_DIV32; reload = (count >> 5);}
|
||||
else if (prescale > 8) {exponent = IWDG_PR_DIV16; reload = (count >> 4);}
|
||||
else if (prescale > 4) {exponent = IWDG_PR_DIV8; reload = (count >> 3);}
|
||||
else {exponent = IWDG_PR_DIV4; reload = (count >> 2);}
|
||||
/* Avoid the undefined situation of a zero count */
|
||||
if (count == 0) count = 1;
|
||||
|
||||
while (iwdg_prescaler_busy());
|
||||
IWDG_KR = IWDG_KR_UNLOCK;
|
||||
IWDG_PR = exponent;
|
||||
while (iwdg_reload_busy());
|
||||
IWDG_KR = IWDG_KR_UNLOCK;
|
||||
IWDG_RLR = (reload & COUNT_MASK);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Get Reload Register Status
|
||||
|
||||
@returns boolean: TRUE if the reload register is busy and unavailable for loading
|
||||
a new count value.
|
||||
*/
|
||||
|
||||
bool iwdg_reload_busy(void)
|
||||
{
|
||||
return (IWDG_SR & IWDG_SR_RVU);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Get Prescaler Register Status
|
||||
|
||||
@returns boolean: TRUE if the prescaler register is busy and unavailable for loading
|
||||
a new period value.
|
||||
*/
|
||||
|
||||
bool iwdg_prescaler_busy(void)
|
||||
{
|
||||
return (IWDG_SR & IWDG_SR_PVU);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG reset Watchdog Timer
|
||||
|
||||
The watchdog timer is reset. The counter restarts from the value in the reload
|
||||
register.
|
||||
*/
|
||||
|
||||
void iwdg_reset(void)
|
||||
{
|
||||
IWDG_KR = IWDG_KR_RESET;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
727
lib/stm32/common/spi_common_all.c
Normal file
727
lib/stm32/common/spi_common_all.c
Normal file
@@ -0,0 +1,727 @@
|
||||
/** @addtogroup spi_file
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
|
||||
|
||||
@date 15 October 2012
|
||||
|
||||
Devices can have up to three SPI peripherals. The common 4-wire full-duplex
|
||||
mode of operation is supported, along with 3-wire variants using unidirectional
|
||||
communication modes or half-duplex bidirectional communication. A variety of
|
||||
options allows many of the SPI variants to be supported. Multimaster operation
|
||||
is also supported. A CRC can be generated and checked in hardware.
|
||||
|
||||
@note Some JTAG pins need to be remapped if SPI is to be used.
|
||||
|
||||
@note The I2S protocol shares the SPI hardware so the two protocols cannot be
|
||||
used at the same time on the same peripheral.
|
||||
|
||||
Example: 1Mbps, positive clock polarity, leading edge trigger, 8-bit words,
|
||||
LSB first.
|
||||
@code
|
||||
spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
|
||||
SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
|
||||
SPI_CR1_LSBFIRST);
|
||||
spi_write(SPI1, 0x55); // 8-bit write
|
||||
spi_write(SPI1, 0xaa88); // 16-bit write
|
||||
reg8 = spi_read(SPI1); // 8-bit read
|
||||
reg16 = spi_read(SPI1); // 16-bit read
|
||||
@endcode
|
||||
|
||||
@todo need additional functions to aid ISRs in retrieving status
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/spi.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
/*
|
||||
* SPI and I2S code.
|
||||
*
|
||||
* Examples:
|
||||
* spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
|
||||
* SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
|
||||
* SPI_CR1_LSBFIRST);
|
||||
* spi_write(SPI1, 0x55); // 8-bit write
|
||||
* spi_write(SPI1, 0xaa88); // 16-bit write
|
||||
* reg8 = spi_read(SPI1); // 8-bit read
|
||||
* reg16 = spi_read(SPI1); // 16-bit read
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Reset.
|
||||
|
||||
The SPI peripheral and all its associated configuration registers are placed in the
|
||||
reset condition. The reset is effected via the RCC peripheral reset system.
|
||||
|
||||
@param[in] spi_peripheral Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_reset(u32 spi_peripheral)
|
||||
{
|
||||
switch (spi_peripheral) {
|
||||
case SPI1:
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_SPI1RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_SPI1RST);
|
||||
break;
|
||||
case SPI2:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
|
||||
break;
|
||||
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F3) || defined(STM32F4)
|
||||
case SPI3:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Configure the SPI as Master.
|
||||
|
||||
The SPI peripheral is configured as a master with communication parameters
|
||||
baudrate, data format 8/16 bits, frame format lsb/msb first, clock polarity
|
||||
and phase. The SPI enable, CRC enable and CRC next controls are not affected.
|
||||
These must be controlled separately.
|
||||
|
||||
@todo NSS pin handling.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
@param[in] br Unsigned int32. Baudrate @ref spi_baudrate.
|
||||
@param[in] cpol Unsigned int32. Clock polarity @ref spi_cpol.
|
||||
@param[in] cpha Unsigned int32. Clock Phase @ref spi_cpha.
|
||||
@param[in] dff Unsigned int32. Data frame format 8/16 bits @ref spi_dff.
|
||||
@param[in] lsbfirst Unsigned int32. Frame format lsb/msb first @ref spi_lsbfirst.
|
||||
@returns int. Error code.
|
||||
*/
|
||||
|
||||
int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst)
|
||||
{
|
||||
u32 reg32 = SPI_CR1(spi);
|
||||
|
||||
/* Reset all bits omitting SPE, CRCEN and CRCNEXT bits. */
|
||||
reg32 &= SPI_CR1_SPE | SPI_CR1_CRCEN | SPI_CR1_CRCNEXT;
|
||||
|
||||
reg32 |= SPI_CR1_MSTR; /* Configure SPI as master. */
|
||||
|
||||
reg32 |= br; /* Set baud rate bits. */
|
||||
reg32 |= cpol; /* Set CPOL value. */
|
||||
reg32 |= cpha; /* Set CPHA value. */
|
||||
reg32 |= dff; /* Set data format (8 or 16 bits). */
|
||||
reg32 |= lsbfirst; /* Set frame format (LSB- or MSB-first). */
|
||||
|
||||
/* TODO: NSS pin handling. */
|
||||
|
||||
SPI_CR1(spi) = reg32;
|
||||
|
||||
return 0; /* TODO */
|
||||
}
|
||||
|
||||
/* TODO: Error handling? */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable.
|
||||
|
||||
The SPI peripheral is enabled.
|
||||
|
||||
@todo Error handling?
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_SPE; /* Enable SPI. */
|
||||
}
|
||||
|
||||
/* TODO: Error handling? */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable.
|
||||
|
||||
The SPI peripheral is disabled.
|
||||
|
||||
@todo Follow procedure from section 23.3.8 in the TRM.
|
||||
(possibly create a "clean disable" function separately)
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable(u32 spi)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = SPI_CR1(spi);
|
||||
reg32 &= ~(SPI_CR1_SPE); /* Disable SPI. */
|
||||
SPI_CR1(spi) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Data Write.
|
||||
|
||||
Data is written to the SPI interface.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
|
||||
*/
|
||||
|
||||
void spi_write(u32 spi, u16 data)
|
||||
{
|
||||
/* Write data (8 or 16 bits, depending on DFF) into DR. */
|
||||
SPI_DR(spi) = data;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Data Write with Blocking.
|
||||
|
||||
Data is written to the SPI interface after the previous write transfer has finished.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
|
||||
*/
|
||||
|
||||
void spi_send(u32 spi, u16 data)
|
||||
{
|
||||
/* Wait for transfer finished. */
|
||||
while (!(SPI_SR(spi) & SPI_SR_TXE))
|
||||
;
|
||||
|
||||
/* Write data (8 or 16 bits, depending on DFF) into DR. */
|
||||
SPI_DR(spi) = data;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Data Read.
|
||||
|
||||
Data is read from the SPI interface after the incoming transfer has finished.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
@returns data Unsigned int16. 8 or 16 bit data.
|
||||
*/
|
||||
|
||||
u16 spi_read(u32 spi)
|
||||
{
|
||||
/* Wait for transfer finished. */
|
||||
while (!(SPI_SR(spi) & SPI_SR_RXNE))
|
||||
;
|
||||
|
||||
/* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
|
||||
return SPI_DR(spi);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Data Write and Read Exchange.
|
||||
|
||||
Data is written to the SPI interface, then a read is done after the incoming transfer
|
||||
has finished.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
|
||||
@returns data Unsigned int16. 8 or 16 bit data.
|
||||
*/
|
||||
|
||||
u16 spi_xfer(u32 spi, u16 data)
|
||||
{
|
||||
spi_write(spi, data);
|
||||
|
||||
/* Wait for transfer finished. */
|
||||
while (!(SPI_SR(spi) & SPI_SR_RXNE))
|
||||
;
|
||||
|
||||
/* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
|
||||
return SPI_DR(spi);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Bidirectional Simplex Mode.
|
||||
|
||||
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
|
||||
(using a clock wire and a bidirectional data wire).
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_bidirectional_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Unidirectional Mode.
|
||||
|
||||
The SPI peripheral is set for unidirectional transfers. This is used in full duplex
|
||||
mode or when the SPI is placed in two-wire simplex mode that uses a clock wire and a
|
||||
unidirectional data wire.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_unidirectional_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_BIDIMODE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
|
||||
|
||||
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
|
||||
(using a clock wire and a bidirectional data wire), and is placed in a receive state.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_bidirectional_receive_only_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
|
||||
SPI_CR1(spi) &= ~SPI_CR1_BIDIOE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
|
||||
|
||||
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
|
||||
(using a clock wire and a bidirectional data wire), and is placed in a transmit state.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_bidirectional_transmit_only_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
|
||||
SPI_CR1(spi) |= SPI_CR1_BIDIOE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable the CRC.
|
||||
|
||||
The SPI peripheral is set to use a CRC field for transmit and receive.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_crc(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_CRCEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable the CRC.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_crc(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_CRCEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Next Transmit is a Data Word
|
||||
|
||||
The next transmission to take place is a data word from the transmit buffer.
|
||||
This must be called before transmission to distinguish between sending
|
||||
of a data or CRC word.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_next_tx_from_buffer(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_CRCNEXT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Next Transmit is a CRC Word
|
||||
|
||||
The next transmission to take place is a crc word from the hardware crc unit.
|
||||
This must be called before transmission to distinguish between sending
|
||||
of a data or CRC word.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_next_tx_from_crc(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_CRCNEXT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Data Frame Format to 8 bits
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_dff_8bit(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_DFF;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Data Frame Format to 16 bits
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_dff_16bit(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_DFF;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Full Duplex (3-wire) Mode
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_full_duplex_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_RXONLY;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set Receive Only Mode for Simplex (2-wire) Unidirectional Transfers
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_receive_only_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_RXONLY;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable Slave Management by Hardware
|
||||
|
||||
In slave mode the NSS hardware input is used as a select enable for the slave.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_software_slave_management(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_SSM;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable Slave Management by Software
|
||||
|
||||
In slave mode the NSS hardware input is replaced by an internal software
|
||||
enable/disable of the slave (@ref spi_set_nss_high).
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_software_slave_management(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_SSM;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Software NSS Signal High
|
||||
|
||||
In slave mode, and only when software slave management is used, this replaces
|
||||
the NSS signal with a slave select enable signal.
|
||||
|
||||
@todo these should perhaps be combined with an SSM enable as it is meaningless otherwise
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_nss_high(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_SSI;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Software NSS Signal Low
|
||||
|
||||
In slave mode, and only when software slave management is used, this replaces
|
||||
the NSS signal with a slave select disable signal.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_nss_low(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_SSI;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set to Send LSB First
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_send_lsb_first(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_LSBFIRST;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set to Send MSB First
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_send_msb_first(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_LSBFIRST;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Baudrate Prescaler
|
||||
|
||||
@todo Why is this specification different to the spi_init_master baudrate values?
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
@param[in] baudrate Unsigned int8. Baudrate prescale value @ref spi_br_pre.
|
||||
*/
|
||||
|
||||
void spi_set_baudrate_prescaler(u32 spi, u8 baudrate)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
if (baudrate > 7)
|
||||
return;
|
||||
|
||||
reg32 = (SPI_CR1(spi) & 0xffc7); /* Clear bits [5:3]. */
|
||||
reg32 |= (baudrate << 3);
|
||||
SPI_CR1(spi) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set to Master Mode
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_master_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_MSTR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set to Slave Mode
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_slave_mode(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_MSTR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Clock Polarity to High when Idle
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_clock_polarity_1(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_CPOL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Clock Polarity to Low when Idle
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_clock_polarity_0(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_CPOL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Clock Phase to Capture on Trailing Edge
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_clock_phase_1(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) |= SPI_CR1_CPHA;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the Clock Phase to Capture on Leading Edge
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_set_clock_phase_0(u32 spi)
|
||||
{
|
||||
SPI_CR1(spi) &= ~SPI_CR1_CPHA;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable the Transmit Buffer Empty Interrupt
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_tx_buffer_empty_interrupt(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) |= SPI_CR2_TXEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable the Transmit Buffer Empty Interrupt
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_tx_buffer_empty_interrupt(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) &= ~SPI_CR2_TXEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable the Receive Buffer Ready Interrupt
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_rx_buffer_not_empty_interrupt(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) |= SPI_CR2_RXNEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable the Receive Buffer Ready Interrupt
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_rx_buffer_not_empty_interrupt(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) &= ~SPI_CR2_RXNEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable the Error Interrupt
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_error_interrupt(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) |= SPI_CR2_ERRIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable the Error Interrupt
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_error_interrupt(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) &= ~SPI_CR2_ERRIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the NSS Pin as an Output
|
||||
|
||||
Normally used in master mode to allows the master to place all devices on the
|
||||
SPI bus into slave mode. Multimaster mode is not possible.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_ss_output(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) |= SPI_CR2_SSOE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Set the NSS Pin as an Input
|
||||
|
||||
In master mode this allows the master to sense the presence of other masters. If
|
||||
NSS is then pulled low the master is placed into slave mode. In slave mode NSS
|
||||
becomes a slave enable.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_ss_output(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) &= ~SPI_CR2_SSOE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable Transmit Transfers via DMA
|
||||
|
||||
This allows transmissions to proceed unattended using DMA to move data to the
|
||||
transmit buffer as it becomes available. The DMA channels provided for each
|
||||
SPI peripheral are given in the Technical Manual DMA section.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_tx_dma(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) |= SPI_CR2_TXDMAEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable Transmit Transfers via DMA
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_tx_dma(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) &= ~SPI_CR2_TXDMAEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Enable Receive Transfers via DMA
|
||||
|
||||
This allows received data streams to proceed unattended using DMA to move data from
|
||||
the receive buffer as data becomes available. The DMA channels provided for each
|
||||
SPI peripheral are given in the Technical Manual DMA section.
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_enable_rx_dma(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) |= SPI_CR2_RXDMAEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief SPI Disable Receive Transfers via DMA
|
||||
|
||||
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
|
||||
*/
|
||||
|
||||
void spi_disable_rx_dma(u32 spi)
|
||||
{
|
||||
SPI_CR2(spi) &= ~SPI_CR2_RXDMAEN;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
452
lib/stm32/common/usart_common_all.c
Normal file
452
lib/stm32/common/usart_common_all.c
Normal file
@@ -0,0 +1,452 @@
|
||||
/** @addtogroup usart_file
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
|
||||
@date 30 August 2012
|
||||
|
||||
This library supports the USART/UART in the STM32F series
|
||||
of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
Devices can have up to 3 USARTs and 2 UARTs.
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Set Baudrate.
|
||||
|
||||
The baud rate is computed from the APB high-speed prescaler clock (for USART1)
|
||||
or the APB low-speed prescaler clock (for other USARTs). These values must
|
||||
be correctly set before calling this function (refer to the rcc_clock_setup-*
|
||||
functions in RCC).
|
||||
|
||||
@todo Add support for USART6 and oversampling in F2/F4
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] baud unsigned 32 bit. Baud rate specified in Hz.
|
||||
*/
|
||||
|
||||
void usart_set_baudrate(u32 usart, u32 baud)
|
||||
{
|
||||
u32 clock = rcc_ppre1_frequency;
|
||||
|
||||
//#ifdef STM32F1
|
||||
if (usart == USART1) {
|
||||
clock = rcc_ppre2_frequency;
|
||||
}
|
||||
/* This has to be added for F2 when it get's support for USART6 */
|
||||
/*
|
||||
#else
|
||||
if ((usart == USART1) ||
|
||||
(usart == USART6)) {
|
||||
clock = rcc_ppre2_frequency;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
/*
|
||||
* Yes it is as simple as that. The reference manual is
|
||||
* talking about fractional calculation but it seems to be only
|
||||
* marketting babble to sound awesome. It is nothing else but a
|
||||
* simple divider to generate the correct baudrate.
|
||||
*
|
||||
* Note: We round() the value rather than floor()ing it, for more
|
||||
* accurate divisor selection.
|
||||
*/
|
||||
USART_BRR(usart) = ((2 * clock) + baud) / (2 * baud);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Set Word Length.
|
||||
|
||||
The word length is set to 8 or 9 bits. Note that the last bit will be a parity bit
|
||||
if parity is enabled, in which case the data length will be 7 or 8 bits respectively.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] bits unsigned 32 bit. Word length in bits 8 or 9.
|
||||
*/
|
||||
|
||||
void usart_set_databits(u32 usart, u32 bits)
|
||||
{
|
||||
if (bits == 8)
|
||||
USART_CR1(usart) &= ~USART_CR1_M; /* 8 data bits */
|
||||
else
|
||||
USART_CR1(usart) |= USART_CR1_M; /* 9 data bits */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Set Stop Bit(s).
|
||||
|
||||
The stop bits are specified as 0.5, 1, 1.5 or 2.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] stopbits unsigned 32 bit. Stop bits @ref usart_cr2_stopbits.
|
||||
*/
|
||||
|
||||
void usart_set_stopbits(u32 usart, u32 stopbits)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = USART_CR2(usart);
|
||||
reg32 = (reg32 & ~USART_CR2_STOPBITS_MASK) | stopbits;
|
||||
USART_CR2(usart) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Set Parity.
|
||||
|
||||
The parity bit can be selected as none, even or odd.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] parity unsigned 32 bit. Parity @ref usart_cr1_parity.
|
||||
*/
|
||||
|
||||
void usart_set_parity(u32 usart, u32 parity)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = USART_CR1(usart);
|
||||
reg32 = (reg32 & ~USART_PARITY_MASK) | parity;
|
||||
USART_CR1(usart) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Set Rx/Tx Mode.
|
||||
|
||||
The mode can be selected as Rx only, Tx only or Rx+Tx.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] mode unsigned 32 bit. Mode @ref usart_cr1_mode.
|
||||
*/
|
||||
|
||||
void usart_set_mode(u32 usart, u32 mode)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = USART_CR1(usart);
|
||||
reg32 = (reg32 & ~USART_MODE_MASK) | mode;
|
||||
USART_CR1(usart) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Set Hardware Flow Control.
|
||||
|
||||
The flow control bit can be selected as none, RTS, CTS or RTS+CTS.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] flowcontrol unsigned 32 bit. Flowcontrol @ref usart_cr3_flowcontrol.
|
||||
*/
|
||||
|
||||
void usart_set_flow_control(u32 usart, u32 flowcontrol)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = USART_CR3(usart);
|
||||
reg32 = (reg32 & ~USART_FLOWCONTROL_MASK) | flowcontrol;
|
||||
USART_CR3(usart) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Enable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_enable(u32 usart)
|
||||
{
|
||||
USART_CR1(usart) |= USART_CR1_UE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Disable.
|
||||
|
||||
At the end of the current frame, the USART is disabled to reduce power.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_disable(u32 usart)
|
||||
{
|
||||
USART_CR1(usart) &= ~USART_CR1_UE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Send a Data Word.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] data unsigned 16 bit.
|
||||
*/
|
||||
|
||||
void usart_send(u32 usart, u16 data)
|
||||
{
|
||||
/* Send data. */
|
||||
USART_DR(usart) = (data & USART_DR_MASK);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Read a Received Data Word.
|
||||
|
||||
If parity is enabled the MSB (bit 7 or 8 depending on the word length) is the parity bit.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@returns unsigned 16 bit data word.
|
||||
*/
|
||||
|
||||
u16 usart_recv(u32 usart)
|
||||
{
|
||||
/* Receive data. */
|
||||
return USART_DR(usart) & USART_DR_MASK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Wait for Transmit Data Buffer Empty
|
||||
|
||||
Blocks until the transmit data buffer becomes empty and is ready to accept the
|
||||
next data word.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_wait_send_ready(u32 usart)
|
||||
{
|
||||
/* Wait until the data has been transferred into the shift register. */
|
||||
while ((USART_SR(usart) & USART_SR_TXE) == 0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Wait for Received Data Available
|
||||
|
||||
Blocks until the receive data buffer holds a valid received data word.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_wait_recv_ready(u32 usart)
|
||||
{
|
||||
/* Wait until the data is ready to be received. */
|
||||
while ((USART_SR(usart) & USART_SR_RXNE) == 0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Send Data Word with Blocking
|
||||
|
||||
Blocks until the transmit data buffer becomes empty then writes the next data word
|
||||
for transmission.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] data unsigned 16 bit.
|
||||
*/
|
||||
|
||||
void usart_send_blocking(u32 usart, u16 data)
|
||||
{
|
||||
usart_wait_send_ready(usart);
|
||||
usart_send(usart, data);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Read a Received Data Word with Blocking.
|
||||
|
||||
Wait until a data word has been received then return the word.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@returns unsigned 16 bit data word.
|
||||
*/
|
||||
|
||||
u16 usart_recv_blocking(u32 usart)
|
||||
{
|
||||
usart_wait_recv_ready(usart);
|
||||
|
||||
return usart_recv(usart);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Receiver DMA Enable.
|
||||
|
||||
DMA is available on:
|
||||
@li USART1 Rx DMA1 channel 5.
|
||||
@li USART2 Rx DMA1 channel 6.
|
||||
@li USART3 Rx DMA1 channel 3.
|
||||
@li UART4 Rx DMA2 channel 3.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_enable_rx_dma(u32 usart)
|
||||
{
|
||||
USART_CR3(usart) |= USART_CR3_DMAR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Receiver DMA Disable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_disable_rx_dma(u32 usart)
|
||||
{
|
||||
USART_CR3(usart) &= ~USART_CR3_DMAR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Transmitter DMA Enable.
|
||||
|
||||
DMA is available on:
|
||||
@li USART1 Tx DMA1 channel 4.
|
||||
@li USART2 Tx DMA1 channel 7.
|
||||
@li USART3 Tx DMA1 channel 2.
|
||||
@li UART4 Tx DMA2 channel 5.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_enable_tx_dma(u32 usart)
|
||||
{
|
||||
USART_CR3(usart) |= USART_CR3_DMAT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Transmitter DMA Disable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_disable_tx_dma(u32 usart)
|
||||
{
|
||||
USART_CR3(usart) &= ~USART_CR3_DMAT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Receiver Interrupt Enable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_enable_rx_interrupt(u32 usart)
|
||||
{
|
||||
USART_CR1(usart) |= USART_CR1_RXNEIE;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Receiver Interrupt Disable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_disable_rx_interrupt(u32 usart)
|
||||
{
|
||||
USART_CR1(usart) &= ~USART_CR1_RXNEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Transmitter Interrupt Enable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_enable_tx_interrupt(u32 usart)
|
||||
{
|
||||
USART_CR1(usart) |= USART_CR1_TXEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Transmitter Interrupt Disable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_disable_tx_interrupt(u32 usart)
|
||||
{
|
||||
USART_CR1(usart) &= ~USART_CR1_TXEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Error Interrupt Enable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_enable_error_interrupt(u32 usart)
|
||||
{
|
||||
USART_CR3(usart) |= USART_CR3_EIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief USART Error Interrupt Disable.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
|
||||
void usart_disable_error_interrupt(u32 usart)
|
||||
{
|
||||
USART_CR3(usart) &= ~USART_CR3_EIE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief USART Read a Status Flag.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
|
||||
@returns boolean: flag set.
|
||||
*/
|
||||
|
||||
bool usart_get_flag(u32 usart, u32 flag)
|
||||
{
|
||||
return ((USART_SR(usart) & flag) != 0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief USART Return Interrupt Source.
|
||||
|
||||
Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was
|
||||
set and the interrupt was enabled. If the specified flag is not an interrupt
|
||||
flag, the function returns false.
|
||||
|
||||
@todo These are the most important interrupts likely to be used. Others
|
||||
relating to LIN break, and error conditions in multibuffer communication, need
|
||||
to be added for completeness.
|
||||
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
|
||||
@returns boolean: flag and interrupt enable both set.
|
||||
*/
|
||||
|
||||
bool usart_get_interrupt_source(u32 usart, u32 flag)
|
||||
{
|
||||
u32 flag_set = (USART_SR(usart) & flag);
|
||||
/* IDLE, RXNE, TC, TXE interrupts */
|
||||
if ((flag >= USART_SR_IDLE) && (flag <= USART_SR_TXE))
|
||||
return ((flag_set & USART_CR1(usart)) != 0);
|
||||
/* Overrun error */
|
||||
else if (flag == USART_SR_ORE)
|
||||
return (flag_set && (USART_CR3(usart) & USART_CR3_CTSIE));
|
||||
return (false);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
Reference in New Issue
Block a user