在线时间372 小时
UID3135871
注册时间2016-10-9
NXP金币20
TA的每日心情 | 怒 2024-2-5 12:06 |
---|
签到天数: 627 天 [LV.9]以坛为家II
版主
- 积分
- 4429
- 最后登录
- 2024-2-5
|
本帖最后由 胤幻1988 于 2020-10-10 16:26 编辑
今天弄了下LPC824的USART_DMA ,官方给的例子直接就AB乒乓链接操作了。
乍一看,还是有的脑门疼。我这里先弄个简单的,就1路,不能循环。
定义了userkey 中断作为DMA的触发信号。代码在上次的代码上修改,其他没变
添加了几个函数文件。
////////////////////////////////////////////////
key.c文件:
#include "key.h"
void PINT_Init_Key_User(void)
{
LPC_GPIO_PORT->DIRCLR0 = 1 << KEY_USER; // 配置USER_KEY对应的引脚为输入
LPC_SYSCON->PINTSEL[PINTSEL0] = KEY_USER; // USER_KEY对应对应到引脚中断0(PINTSEL0)
LPC_PIN_INT->ISEL = 0 << PINTSEL0; // 配置引脚中断0(PINTSEL0)为边沿触发
LPC_PIN_INT->IENR = 1 << PINTSEL0; // 配置引脚中断0(PINTSEL0)是上升沿触发
LPC_PIN_INT->IENF = 0 << PINTSEL0; // 配置引脚中断0(PINTSEL0)不是下降沿触发
LPC_PIN_INT->IST = 0xFF; // 清除所有可能的引脚中断标志
NVIC_EnableIRQ(PININT0_IRQn); // 使能引脚中断
}
////////////////////////////////////////////////
key.h文件:
#ifndef __KEY_H_
#define __KEY_H_
#include "LPC8xx.h"
#include "lpc8xx_swm.h"
#include "lpc8xx_syscon.h"
#include "utilities.h"
#define PINTSEL0 0 // 定义引脚中断0的编号
#define KEY_USER P0_1 // 定义按键USER_KEY的引脚
void PINT_Init_Key_User(void);
#endif
////////////////////////////////////////////////
dma_usart0.C文件:
#include "dma_usart0.h"
// Instantiate the channel descriptor table, which must be 512-byte aligned (see lpc8xx_dma.h)
ALIGN(512) DMA_CHDESC_T Chan_Desc_Table[NUM_DMA_CHANNELS];//NUM_DMA_CHANNELS=18 共18种通道源
// Instantiate one reload descriptor. All descriptors must be 16-byte aligned (see lpc8xx_dma.h)
ALIGN(16) DMA_RELOADDESC_T Reload_Descriptor_B;
uint8_t DMA_IntA_Flag; // 中断A软件标志
void DMA_USART0_Send(uint8_t *buf,uint32_t length)
{
uint32_t ch_cfg_val,xfercount,xfercfg;
// Reset the DMA, and enable clocks to peripherals (see lpc8xx_syscon.h)
// LPC_SYSCON->PRESETCTRL &= (DMA_RST_N);//复位 DMA
// LPC_SYSCON->PRESETCTRL |= ~(DMA_RST_N);
LPC_SYSCON->SYSAHBCLKCTRL |= (DMA | UART0);//使能模块时钟
LPC_DMA->CTRL=0;//使能DMA,然后再配置
LPC_DMA->SRAMBASE = (uint32_t)(&Chan_Desc_Table);//DMA控制器所有描述链头的地址
xfercount=length-1;//数据块传输长度
// Setup the channel's CFG register
//
// CFG1
// PERIPREQEN = 1 The peripheral DMA request is enabled
// HWTRIGEN = 0 Hardware triggering is disabled
// TRIGPOL = 0 Active low or falling edge hardware trigger (not used)
// TRIGTYPE = 0 Edge sensitive hardware trigger (not used)
// TRIGBURST = 0 Single transfer will be launched by each trigger
// BURSTPOWER = 0 Unused
// SRCBURSTWRAP = 0 Unused
// DSTBURSTWRAP = 0 Unused
// CHPRIORITY = 0 Highest priority
ch_cfg_val = 1<<DMA_CFG_PERIPHREQEN | //外设请求
1<<DMA_CFG_HWTRIGEN | //硬件触发
0<<DMA_CFG_TRIGPOL | //下降沿触发
0<<DMA_CFG_TRIGTYPE | //边沿触发
0<<DMA_CFG_TRIGBURST |
0<<DMA_CFG_BURSTPOWER |
0<<DMA_CFG_SRCBURSTWRAP |
0<<DMA_CFG_DSTBURSTWRAP |
0<<DMA_CFG_CHPRIORITY;
LPC_DMA->CHANNEL[CH_USART0_TX].CFG = ch_cfg_val;//配置写入寄存器
// Build the initial channel XFERCFG for the A sequence
//
// XFERCFG1
// CFGVALID = 1 Current channel descriptor is considered valid
// RELOAD = 1 Reload the control structure (the contents of this register) when the descriptor is exhausted
// SWTRIG = 0 Don't trigger now
// CLRTRIG = 0 The trigger is not cleared when this descriptor is exhausted
// SETINTA = 1 Set the INTA flag when this descriptor is exhausted
// SETINTB = 0 Don't use the INTB flag
// WIDTH = 0 Eight-bit transfers
// SRCINC = 1 Source address is incremented by 1 x WIDTH (source is buffer in memory)
// DSTINC = 0 Destination address is not incremented (destination is TXDAT register of UART)
// XFERCOUNT = Length of string (less the CR, less the LF, less the NUL terminator) minus 1
xfercfg = 0<<DMA_XFERCFG_CFGVALID | //暂时设置为无效
0<<DMA_XFERCFG_RELOAD | //没有下一个描述符
0<<DMA_XFERCFG_SWTRIG | //没有软件触发
1<<DMA_XFERCFG_CLRTRIG | //传输结束时清除触发标志
1<<DMA_XFERCFG_SETINTA | //传输结束时设置INTA中断
0<<DMA_XFERCFG_SETINTB |
0<<DMA_XFERCFG_WIDTH | //数据宽度为8位
1<<DMA_XFERCFG_SRCINC | //每次传输后源地址递增
0<<DMA_XFERCFG_DSTINC | //每次传输后目标地址不递增
xfercount<<DMA_XFERCFG_XFERCOUNT;// 传输长度
LPC_DMA->CHANNEL[CH_USART0_TX].XFERCFG = xfercfg; //配置写入寄存器 // Initial XFERCFG
// 填写通道描述符链头 指定存放的位置
Chan_Desc_Table[CH_USART0_TX].source = (uint32_t)(&buf[xfercount]); // Initial source data end address (start address + (xfercount*srcinc))
Chan_Desc_Table[CH_USART0_TX].dest = (uint32_t)(&LPC_USART0->TXDAT); // Initial destination data end address
Chan_Desc_Table[CH_USART0_TX].next = (uint32_t)0L; // Initial next points to Reload Descriptor B
// 使能对应通道的中断
LPC_DMA->INTENSET0 = 1<<CH_USART0_TX;
//使能对应的DMA通道
LPC_DMA->ENABLESET0 = 1<<CH_USART0_TX;
// 使能整个DMA控制器
LPC_DMA->CTRL = 1;
//设置传输描述符为有效
LPC_DMA->SETVALID0 = 1<<CH_USART0_TX;
//配置DMA触发源为“引脚中断0”
LPC_DMATRIGMUX->DMA_ITRIG_INMUX1 = 0x05;
//使能中断
NVIC_EnableIRQ(DMA_IRQn);
}
////////////////////////////////////////////////
dma_usart0.h文件:
#ifndef __DMA_USART0_H_
#define __DMA_USART0_H_
#include "lpc_types.h"
#include "LPC8xx.h"
#include "lpc8xx_dma.h"
#include "lpc8xx_syscon.h"
#include "utilities.h"
//P93
#define CH_USART0_RX 0 //USART0 对应DMA通道
#define CH_USART0_TX 1 //USART0 对应DMA通道
extern uint8_t DMA_IntA_Flag; // 中断A软件标志
void DMA_USART0_Send(uint8_t *buf,uint32_t length);
#endif
////////////////////////////////////////////////
在中断函数main.isr里面添加KEY中断和DMA中断
void DMA_IRQHandler(void)
{
//清除中断标志,同时对软件标志A计数
if (LPC_DMA->INTA0 & (1 << CH_USART0_TX))
{
LPC_DMA->INTA0 = 1 << CH_USART0_TX;
DMA_IntA_Flag++;
}
//清除可能的错误中断
if (LPC_DMA->ERRINT0 & (1 << CH_USART0_TX))
{
LPC_DMA->ERRINT0 = 1 << CH_USART0_TX;
}
//printf("IN the dma interrupt!\r\n");
}
void PININT0_IRQHandler(void)
{
if (LPC_PIN_INT->RISE & (1<<PINTSEL0))
LPC_PIN_INT->RISE = 1<<PINTSEL0; // 清除上升沿中断标志
if (LPC_PIN_INT->FALL & (1<<PINTSEL0))
LPC_PIN_INT->FALL = 1<<PINTSEL0; // 清除下降沿中断标志
//printf("IN the key interrupt!\r\n");
}
////////////////////////////////////////////////
在main函数里面修改:
const unsigned char Hello[] = "Hello DMA World!\r\n"; // 待发送的数据串
const unsigned char Hello1[] = "Hello1 DMA World!\r\n"; // 待发送的数据串
int main(void)
{
uint16_t i=0,length=0;
uint8_t tmpbuf[100]={0};
GPIOInit();
USART0_Init();
LED_Init();
PINT_Init_Key_User();
DMA_IntA_Flag = 0; // 清除DMA中断标记
DMA_USART0_Send((uint8_t *)Hello, sizeof(Hello)-1); // 初始化DMA控制器
do{
//printf("wait answer!\r\n");
//delay_ms(20);
}
while(DMA_IntA_Flag == 0);
DMA_IntA_Flag = 0; // 清除DMA中断标记
DMA_USART0_Send((uint8_t *)Hello1, sizeof(Hello1)-1);
do{
//printf("wait answer!\r\n");
//delay_ms(20);
}
while(DMA_IntA_Flag == 0);
while(1)
{
if(DMA_IntA_Flag>0)
{
i++;
DMA_IntA_Flag=0;
length=sprintf(tmpbuf,"the key enter %d times!\r\n",i);
DMA_USART0_Send((uint8_t *)tmpbuf, length-1);
}
}
}
////////////////////////////////////////////////
编译,下载
按第1按键,串口打印出:Hello DMA World!
按第2按键,串口打印出:Hello DMA World!
按第3按键,串口打印出:the key enter 1 times!
按第4按键,串口打印出:the key enter 2 times!
按第5按键,串口打印出:the key enter 3 times!
...
整理了一边,现在看官方例子,果然好懂了。OVER!
|
|