标题:
STM8L的DMA详解 含例程
[打印本页]
作者:
51hei小林
时间:
2016-10-10 00:07
标题:
STM8L的DMA详解 含例程
STM8L有DMA功能,STM8S没有这个功能.DMA用于传输数据,可以把内存中的数据(比如一个存放数据的数组),传递给外设(比如可以将数据传递到USART的发送数据寄存器),当然也可以反向,从外设的寄存器传递给内存,DMA的第四个通道还具有,将数据从内存传递到内存的功能.传递数据时,不占用CPU资源.
如上图,STM8L拥有四个DMA通道,每个通道都可以响应DMA请求,独立传送数据.如果四个通道同时收到DMA请求,DMA控制器会根据软件优先级和硬件优先,决定响应的先后顺序.
上图是支持DMA传输数据的外设,从上图还可以看到具体每个外设对应哪一个DMA通道,这个对编程很重.
上图是DMA的配置流程,基本的配置如下:
①配置外设寄存器地址
②配置内存寄存器地址
③配置传输数据的字节数
④设置通道优先级
⑤设置数据传输方向,是否自动连续传输,传输数据是16位还是8位,
⑥使能DMA通道
⑦是DMA通道总开关
本例程,使用DMA传送数据到USART的发送寄存器,周期性的重置DMA,重新发送数据。
/*硬件连接*/
// PC3(TX)---->
/****************************************************************************************
*开发环境:IAR for stm8 v6.5.3
*硬件平台:STM8L-DISCOVERY
*功能说明:使用DMA通道1传送数据到USART的发送寄存器 USART1_DR,周期性的发送数组中的数据
* 对比.
*作 者:茗风
****************************************************************************************/
#include"iostm8l152c6.h"
#include"stdbool.h"
#include"stdint.h"
#define TXBUF_SIZE 9
#define RXBUF_SIZE 25
#define USART1_DR_ADRESS 0x5231
bool bTX_finished=false;
bool bRX_finished=false;//串口接收完一帧数据标志位
uint8_t ui8TX_number = 0;
uint8_t ui8RX_counter=0;
uint8_t ui8TX_buffer[TXBUF_SIZE]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99};
uint8_t ui8RX_buffer[RXBUF_SIZE];
/******************************************************************************************************
* 名 称:void delay_10ms(uint8_t x_ms)
* 功 能:延时10ms
* 入口参数:无
* 出口参数:无
* 说 明:
* 范 例:无
******************************************************************************************************/
void delay_100ms(void)
{
uint8_t i,j;
for(i=0;i<255;i++)//2*255个指令周期
for(j=0;j<255;j++);//2*255个指令周期
//delay_10ms共消耗 x_ms*2*255+2*x_ms个指令周期
//255*2*255+2*255=130610us=130ms
//此延时函数,延时时间为130ms
//16M/8/2=1M 一个指令周期为1us
}
/******************************************************************************************************
* 名 称:void GPIO_Init(void)
* 功 能:初始化PC7为高速推挽输出
* 入口参数:无
* 出口参数:无
* 说 明:测量系统时钟频率的IO,测量到的频率是:目标时钟源/2/6
* 范 例:无
******************************************************************************************************/
void GPIO_Init(void)
{
PC_CR1_C17 =1;//推挽输出
PC_CR2_C27 =1;//高速输出
PC_DDR_DDR7 =1;//PC4输出
// PC_ODR_ODR7 =0;//输出低电平
}
/******************************************************************************************************
* 名 称:void UART_Init(void)
* 功 能:UART定时器初始化系统
* 入口 参数:无
* 出口 参数:无
* 说 明:UART初始化为 9600 1 8 n
* 范 例:无
******************************************************************************************************/
void UART_Init(void)
{
/*********************************/
PC_DDR_DDR2 =0;//输入
PC_CR1_C12 =1;//上拉输入
PC_CR2_C22 =0;
PC_ODR_ODR3 =1;
PC_CR1_C13 =1;//推挽输出
PC_CR2_C23 =1;//输出摆率10M
PC_DDR_DDR3 =1;//输出高电平,TX空闲状态为高电平,如果不设置,会莫名奇妙的发送0x00
CLK_PCKENR1_PCKEN15=1;//开启USART外设时钟
//开启引脚的UART功能
//00: USART1_TX on PC3 and USART1_RX on PC2
//01: USART1_TX on PA2 and USART1_RX on PA3
//10: USART1_TX on PC5 and USART1_RX on PC6
SYSCFG_RMPCR1_USART1TR_REMAP =0;//PC2,PC3
//如果需要使用其他引脚作为串口发送接收引脚,请在这里选择
//设置串口工作方式
USART1_CR1_M =0;//1 start bit,8 data bit,n stop bit
USART1_CR3_STOP0=0;USART1_CR3_STOP1=0;//1 stop bit
//设置波特率
//波特率设置为9600
// 2000000/9600=208 //2000000是此时系统的主时钟频率,默认8分频,16M/8=2M
//208(DEC)=00D0(HEX)
USART1_BRR2 =0x00;//the BRR2 should be programmed before BRR1
USART1_BRR1 =0x0D;
USART1_CR5_DMAT=1;// DMA mode is enabled for transmission.
// USART1_CR2_TEN=0;//使能发送
// USART1_CR2_TIEN=0;//打开发送中断
USART1_CR2_REN=1;//使能接收
USART1_CR2_RIEN=1;//打开接收中断
}
/******************************************************************************************************
* 名 称:void DMA_Config(void)
* 功 能:启用DMA
* 入口参数:无
* 出口参数:无
* 说 明:STM8L152C6属于中等容量MCU,只有一路DAC输出,输出引脚为PF0
* 范 例:无
******************************************************************************************************/
void DMA_Config(void)
{
//------打开DAM时钟------
CLK_PCKENR2_PCKEN24=1;
//------设置传送的字节数,------
DMA1_C1NDTR=9;
//------设置通道优先级------
DMA1_C1SPR_PL0=0;DMA1_C1SPR_PL1=1;
//------设置传送方向------
DMA1_C1CR_DIR=1;
/* 0: Transfer from the peripheral to the memory.
1: Transfer from the memory to the peripheral.*/
//------设置模式------
DMA1_C1CR_CIRC=0;
/* Auto-reload mode
0: Circular mode disabled.
1: Circular mode enabled. */
//------设置增还是减地址------
DMA1_C1CR_MINCDEC=1;
/* 0: Decrement mode.
1: Increment mode.*/
//------设置传送数据位数------
DMA1_C1SPR_TSIZE=0;
/* 0: 8-bit mode
1: 16-bit mode */
//------设置DMA通道1外设地址------
DMA1_C1PARH=(uint8_t)((uint16_t)USART1_DR_ADRESS >> (uint8_t)8);
DMA1_C1PARL=(uint8_t)USART1_DR_ADRESS;
//------设置DMA通道1内存地址------
DMA1_C1M0ARH=(uint8_t)((uint16_t)&ui8TX_buffer >> (uint8_t)8);
DMA1_C1M0ARL=(uint8_t)&ui8TX_buffer;
DMA1_C1CR_EN=1;
DMA1_GCSR_GEN=1;
}
void main(void)
{
// GPIO_Init();
DMA_Config();
UART_Init();
asm("rim"); //enable interrupts
while(1)
{
ui8TX_number=9;
USART1_CR2_TEN=1;//打开发送
delay_100ms();
delay_100ms();
delay_100ms();
delay_100ms();
DMA1_C1CR_EN=0;
DMA1_C1NDTR=9;
DMA1_C1CR_EN=1;
// asm("wfi");
}
}
/*************************************************************************************************** ***
* 名 称: UART_OnTx()
* 功 能: UART的Tx事件处理函数
* 入口参数:无
* 出口参数:无
* 说 明:发送ui8TX_buffer数组中的数据,发送完成后,置位bTX_finished标志位,下一次进入中断后关闭发送
* 范 例:无
******************************************************************************************************/
#pragma vector=USART_T_TXE_vector
__interrupt void USART_TX_ISR (void)
{
static uint8_t cnts=0;
if(bTX_finished && USART1_SR_TC==1)
{
bTX_finished=false;
USART1_CR2_TIEN=0;//关闭发送中断
USART1_CR2_TEN=0;//关闭发送
}
else if(USART1_SR_TC==1)
{
USART1_DR=ui8TX_buffer[cnts++];
if(cnts==ui8TX_number)
{
cnts=0;
bTX_finished=true;
}
}
}
/******************************************************************************************************
* 名 称: UART_OnRx()
* 功 能: UART的Tx事件处理函数
* 入口 参数:无
* 出口 参数:无
* 说 明:
* 范 例:无
******************************************************************************************************/
#pragma vector=USART_R_RXNE_vector
__interrupt void USART_RX_ISR(void)
{
static uint8_t ui8RX_temp=0;
if(USART1_SR_RXNE==1)
{
ui8RX_temp = USART1_DR;
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1