EFM32 DMA/PRS例程

/**************************************************************************//**
* @file
* @brief High Frequaency ADC Sampling using Timer, DMA and PRS
* @author Energy Micro AS
* @version 1.0.0
******************************************************************************
* @section License
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
*******************************************************************************
*
* This file is licensed under the Silicon Labs Software License Agreement. See
* "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt"
* for details. Before using this software for any purpose, you must agree to the
* terms of that agreement.
*
******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include "efm32.h"
#include "em_chip.h"
#include "em_emu.h"
#include "em_cmu.h"
#include "em_adc.h"
#include "em_lcd.h"
#include "em_prs.h"
#include "em_dma.h"
#include "em_timer.h"
/* Drivers */
#include "segmentlcd.h"
/* Support functions */
#include "support.h"
/* Defines */
#define ADC_SAMPLE_RATE 100000
#define HFPER 14000000
#define TIMER_TOP (HFPER / ADC_SAMPLE_RATE)
#define BUFFER_SIZE_SHIFT 9
#define BUFFER_SIZE (1 << BUFFER_SIZE_SHIFT)
#define BUFFERS_PER_SECOND (ADC_SAMPLE_RATE / BUFFER_SIZE)
#define DMA_CHANNEL 0
#define PRS_CHANNEL 0
/* Uncomment to use Fahrenheit instead of Celsius */
/* #define FAHRENHEIT */
/* DMA control block, must be aligned to 256. */
#if defined (__ICCARM__)
#pragma data_alignment=256
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2];
#elif defined (__CC_ARM)
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2] __attribute__ ((aligned(256)));
#elif defined (__GNUC__)
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2] __attribute__ ((aligned(256)));
#else
#error Undefined toolkit, need to define alignment
#endif
/* Variables */
uint16_t ramBufferA[BUFFER_SIZE];
uint16_t ramBufferB[BUFFER_SIZE];
bool usingRamBufferA;
static DMA_CB_TypeDef cbInData;
char string[8];
/**************************************************************************//**
* @brief ADC0 interrupt handler. Simply clears interrupt flag.
*****************************************************************************/
static void preampDMAInCb(unsigned int channel, bool primary, void *user)
{
(void) user; /* Unused parameter */
/* Refresh DMA */
DMA_RefreshPingPong(channel, /* channel */
primary, /* descriptor to update */
false, /* do not use burst */
NULL, /* do not change destination */
NULL, /* do not change source */
BUFFER_SIZE - 1, /* number of transfers */
false); /* do not stop after completing this cycle */
/* Switch buffer */
usingRamBufferA = primary;
/* Set software interrupt */
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
/**************************************************************************//**
* @brief Software interrupt handler
* Computes and displays the average temperature
*****************************************************************************/
void PendSV_Handler(void)
{
static bool enableAntenna = false;
static uint32_t display_count = 0;
int32_t temp;
uint32_t i;
uint32_t avg = 0;
/* Show Celsius on alphanumeric part of display */
if (usingRamBufferA)
{
for (i = 0; i < BUFFER_SIZE; i++)
{
avg += ramBufferA[i];
}
}
else
{
for (i = 0; i < BUFFER_SIZE; i++)
{
avg += ramBufferB[i];
}
}
/* The buffer size is a power of two, so rightshift can be used instead of
* division */
avg = avg >> BUFFER_SIZE_SHIFT;
#if defined(_EFM32_GIANT_FAMILY)
avg += 112;
#endif
/* Show Celsius or Fahrenheit on alphanumeric part of display */
#ifndef FAHRENHEIT
temp = (int32_t)(convertToCelsius(avg) * 10);
snprintf(string, 8, "%2d,%1d%%C", (temp / 10), abs(temp) % 10);
#else
temp = (int32_t)(convertToFahrenheit(avg) * 10);
snprintf(string, 8, "%2d,%1d%%F", (temp / 10), abs(temp) % 10);
#endif
/* Display result on LCD once a second */
if (++display_count == BUFFERS_PER_SECOND)
{
display_count = 0;
SegmentLCD_Write(string);
/* Indicate update */
SegmentLCD_Symbol(LCD_SYMBOL_ANT, enableAntenna);
enableAntenna = !enableAntenna;
}
}
/**************************************************************************//**
* @brief Configure ADC with DMA
*****************************************************************************/
static void adc_setup(void)
{
/* Configure ADC single conversion */
CMU_ClockEnable(cmuClock_ADC0, true);
ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
init.timebase = ADC_TimebaseCalc(0);
init.warmUpMode = adcWarmupKeepADCWarm;
init.prescale = ADC_PrescaleCalc(7000000, 0);
ADC_Init(ADC0, &init);
singleInit.reference = adcRef1V25;
singleInit.input = adcSingleInpTemp;
singleInit.resolution = adcRes12Bit;
singleInit.prsSel = adcPRSSELCh0;
singleInit.prsEnable = true;
singleInit.acqTime = adcAcqTime32;
ADC_InitSingle(ADC0, &singleInit);
/* Configure DMA usage by ADC */
CMU_ClockEnable(cmuClock_DMA, true);
DMA_CfgDescr_TypeDef descrCfg;
DMA_CfgChannel_TypeDef chnlCfg;
cbInData.cbFunc = preampDMAInCb;
cbInData.userPtr = NULL;
chnlCfg.highPri = true;
chnlCfg.enableInt = true;
chnlCfg.select = DMAREQ_ADC0_SINGLE;
chnlCfg.cb = &cbInData;
DMA_CfgChannel(0, &chnlCfg);
descrCfg.dstInc = dmaDataInc2;
descrCfg.srcInc = dmaDataIncNone;
descrCfg.size = dmaDataSize2;
descrCfg.arbRate = dmaArbitrate1;
descrCfg.hprot = 0;
DMA_CfgDescr(DMA_CHANNEL, true, &descrCfg);
DMA_CfgDescr(DMA_CHANNEL, false, &descrCfg);
DMA_ActivatePingPong(DMA_CHANNEL, /* channel */
false, /* do not use burst */
(void *) &ramBufferA, /* primary destination */
(void *)((uint32_t) &(ADC0->SINGLEDATA)), /* primary source */
BUFFER_SIZE - 1, /* primary number of transfers */
(void *) &ramBufferB, /*altenate deststination */
(void *)((uint32_t) &(ADC0->SINGLEDATA)), /* alternate source */
BUFFER_SIZE - 1); /* alternate number of transfers */
/* Select ramBufferA as current */
usingRamBufferA = true;
}
/**************************************************************************//**
* @brief Configure PRS
*****************************************************************************/
static void prs_setup(unsigned int prsChannel)
{
PRS_LevelSet(0, 1 << (prsChannel + _PRS_SWLEVEL_CH0LEVEL_SHIFT));
PRS_SourceSignalSet(prsChannel,
PRS_CH_CTRL_SOURCESEL_TIMER0,
PRS_CH_CTRL_SIGSEL_TIMER0OF,
prsEdgePos);
}
/**************************************************************************//**
* @brief Configure Timer
*****************************************************************************/
void timer_setup(void)
{
/* Enable clock for TIMER0 module */
CMU_ClockEnable(cmuClock_TIMER0, true);
CMU_ClockEnable(cmuClock_PRS, true);
/* Select TIMER0 parameters */
TIMER_Init_TypeDef timerInit =
{
.enable = true,
.debugRun = true,
.prescale = timerPrescale1,
.clkSel = timerClkSelHFPerClk,
.fallAction = timerInputActionNone,
.riseAction = timerInputActionNone,
.mode = timerModeUp,
.dmaClrAct = false,
.quadModeX4 = false,
.oneShot = false,
.sync = false,
};
/* Set TIMER Top value */
TIMER_TopSet(TIMER0, TIMER_TOP);
/* Configure TIMER */
TIMER_Init(TIMER0, &timerInit);
}
/**************************************************************************//**
* @brief SWO Setup
* Enables code view in energyAware Profiler
*****************************************************************************/
void setupSWO(void)
{
uint32_t *dwt_ctrl = (uint32_t *) 0xE0001000;
uint32_t *tpiu_prescaler = (uint32_t *) 0xE0040010;
uint32_t *tpiu_protocol = (uint32_t *) 0xE00400F0;
CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO;
/* Enable Serial wire output pin */
GPIO->ROUTE |= GPIO_ROUTE_SWOPEN;
#if defined(_EFM32_GIANT_FAMILY)
/* Set location 0 */
GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC0;
/* Enable output on pin - GPIO Port F, Pin 2 */
GPIO->P[5].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK);
GPIO->P[5].MODEL |= GPIO_P_MODEL_MODE2_PUSHPULL;
#else
/* Set location 1 */
GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC1;
/* Enable output on pin */
GPIO->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE15_MASK);
GPIO->P[2].MODEH |= GPIO_P_MODEH_MODE15_PUSHPULL;
#endif
/* Enable debug clock AUXHFRCO */
CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY));
/* Enable trace in core debug */
CoreDebug->DHCSR |= 1;
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
/* Enable PC and IRQ sampling output */
*dwt_ctrl = 0x400113FF;
/* Set TPIU prescaler to 16. */
*tpiu_prescaler = 0xf;
/* Set protocol to NRZ */
*tpiu_protocol = 2;
/* Unlock ITM and output data */
ITM->LAR = 0xC5ACCE55;
ITM->TCR = 0x10009;
}
/******************************************************************************
* @brief Main function
*****************************************************************************/
int main(void)
{
/* Initialize chip */
CHIP_Init();
/* Enable code view */
setupSWO();
SegmentLCD_Init(false);
/* Enable clocks required */
CMU_ClockEnable(cmuClock_HFPER, true);
DMA_Init_TypeDef dmaInit;
dmaInit.hprot = 0;
dmaInit.controlBlock = dmaControlBlock;
DMA_Init(&dmaInit);
/* Configure Timer, PRS and ADC */
timer_setup();
prs_setup(PRS_CHANNEL);
adc_setup();
/* Enable software interrupt */
NVIC_EnableIRQ(PendSV_IRQn);
/* Set priorities */
NVIC_SetPriority(DMA_IRQn, 0); /* Highest priority */
NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1); /* Lowest priority */
/* Stay in this loop forever */
while (1)
{
EMU_EnterEM1();
}
}
EFM32 DMA/PRS例程的更多相关文章
- mmap DMA【转】
转自:http://blog.csdn.net/lihaoweiv/article/details/6275241 第 13 章 mmap 和 DMA 本章将深入探讨 Linux 内存管理部分,并强 ...
- DriverStudio开发PCI设备DMA数据传输
DriverWizard向导可以创建基本的wDM驱动程序框架,包括总线类型,地址空间,中断源,DMA资源,以及IOCTL(i/o控制代码)的定义等等.详细情况可参看DriverStudio的帮助文档, ...
- DMA内存申请--dma_alloc_coherent 及 寄存器与内存【转】
转自:https://blog.csdn.net/ic_soc_arm_robin/article/details/8203933 在项目驱动过程中会经常用到dma传输数据,而dma需要的内存有自己的 ...
- LDD3 第15章 内存映射和DMA
本章内容分为三个部分: 第一部分讲述了mmap系统调用的实现过程.将设备内存直接映射到用户进程的地址空间,尽管不是所有设备都需要,但是能显著的提高设备性能. 如何跨越边界直接访问用户空间的内存页,一些 ...
- linux 简单的DMA例程
一个简单的使用DMA 例子 示例:下面是一个简单的使用DMA进行传输的驱动程序,它是一个假想的设备,只列出DMA相关的部分来说明驱动程序中如何使用DMA的. 函数dad_transfer是设置DMA对 ...
- 【GMT43智能液晶模块】例程十:DMA实验——存储器到存储器的传输
实验原理: DMA(直接存储器访问)传输不需要占用CPU,可以在存储器至存储器实现高速的数据 传输.本实验采用DMA2控制器的数据流0,选用通道0进行数据传输.通过液晶控制传输 和结果显示. 示例截图 ...
- 【iCore4 双核心板_ARM】例程十一:DMA实验——存储器到存储器的传输
实验原理: DAM(直接存储器访问)传输不需要占用CPU,可以在存储器至存储器实现高速的数据 传输.本实验采用DAM2控制器的数据流0,选用通道0进行数据传输.通过LED的颜色来 判断传输是否成功. ...
- 【iCore1S 双核心板_ARM】例程十二:DMA实验——存储器到存储器的传输
实验原理: DAM(直接存储器访问)传输不需要占用CPU,可以在存储器至存储器实现高速的数据 传输.本实验采用DAM2控制器的数据流0,选用通道0进行数据传输.通过LED的颜色来 判断传输是否成功. ...
- 【iCore3 双核心板】例程十一:DMA实验——存储器到存储器的传输
实验指导书及代码包下载: http://pan.baidu.com/s/1bcY5JK iCore3 购买链接: https://item.taobao.com/item.htm?id=5242294 ...
随机推荐
- js hasChildNodes()指针对元素节点子节点多个的话 true
<select multiple size="2"> <option value="bj">北京</option> < ...
- 使用DotNetBarcode制作基本常用条码
核心代码: /// <summary> /// 打印一维码 /// </summary> /// <param name="codeText"> ...
- 利用Windows 2003系统中实现两个网段的路由
利用Windows 2003系统中实现两个网段的路由 当一个局域网中存在两个以上网段时,分属于不同网段内的主机彼此互不可见.为了解决这个问 题,就必须在不同的网段之间设置路由器.如果花费上万元资金购买 ...
- windows named pipe 客户端 服务器
可以实现多客户端对一服务端,服务端为客户端提供服务. 其实一服务端对应每一个client pipe都新建立了一个pipe.windows允许建立多个同名pipe 效果: 服务端代码: #define ...
- nyoj------------找球号(一)
找球号(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 在某一国度里流行着一种游戏.游戏规则为:在一堆球中,每个球上都有一个整数编号i(0&l ...
- ios NSURLSession使用说明及后台工作流程分析
NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的.在程序在前台时,NSURLSession与NSURLConnection可以互为替代工作.注意, ...
- 【LeetCode】42. Trapping Rain Water
Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...
- Python练习笔记——斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一 ...
- asp.net core mvc视频A:笔记3-7.ViewStart与ViewImort
项目位置 放在其它目录应该不会执行! 默认配置 默认配置
- Accounting_会计基础知识
作为企业的财务人员,必须拥有一些技能和财务方面的知识,本文就所讲述的是财务岗位必须掌握的知识总结,仅供参考. 1.账面价值.账面余额和账面净值 账面价值是指某科目(通常是资产类科目)的账面余额减去相关 ...