当前位置:网站首页>stm32使用spi1在slave 模式下 dma 读取数据
stm32使用spi1在slave 模式下 dma 读取数据
2022-08-08 23:04:00 【Jacky_Lu】
初始化 spi1 ,要外部 片选了 pa4 才能进行通信,
pMem=OSMemGet(OSMemC2B,&err);是 ucos2 的函数,就是获得一片内存,可以直接指定一个数组 代替
void InitSpi1DmaRec(void)
{
INT8U err,*pMem,*pTmp;
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//GPIO_SetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //空闲时钟为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //第二个跳变开始采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
//SPI_Cmd(SPI1,ENABLE); //启动接收
SPI_Cmd(SPI1, ENABLE);
Dma_Rx_Init(DMA1_Channel2,(INT32U)&SPI1->DR,0);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
pMem=OSMemGet(OSMemC2B,&err);
DmaGetData(DMA1_Channel2, pMem, 256, &pTmp);
}
在PA4 的外部中断中 获取数据,并传递消息,DmaGetData 是读取dma 数据,并写入下一个 内存块进去
void EXTI4_IRQHandler(void)
{
INT8U *pMem,*pRet,err;
INT32U msg,len;
OSIntEnter();
pMem=OSMemGet(OSMemC2B,&err);
if(err==OS_ERR_NONE)
{
len=DmaGetData(DMA1_Channel2, pMem, 256, &pRet);
msg=(((INT32U)pRet-(INT32U)OSMemBufC2B)/sizeof(OSMemBufC2B[0]))+(len<<8);
OSQPost(OSQTm1629,(void*)msg);
}
CplLed(0);
EXTI_ClearITPendingBit(EXTI_Line4); //清除EXTI0线路挂起位
OSIntExit();
}
dma 的操作函数
/*
USART_DMACmd(USARTX,USART_DMAReq_Tx,ENABLE);
DmaSendData(DMA1_Channel4,(INT8U*)tmpStr,sizeof(tmpStr));
*/
/*---- D M A _ I N I T ----
【功能】:****
【参数】:****
【返回】:****
【说明】:如果采用ucos的话,初始化要放在 OSInit() 之后,因为采用信号量
--------------作者:卢杰西 2009年10月4日 星期日20:30:13--------------------------------*/
//USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
void Dma_Tx_Init(DMA_Channel_TypeDef* chn,u32 dstAddr,u8 bInt)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //启动DMA时钟
/* DMA1 Channel7 configuration ----------------------------------------------*/
DMA_DeInit(chn);
DMA_InitStructure.DMA_PeripheralBaseAddr = dstAddr; //(u32)USART2_DR_Address; //外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0; //内存地址,发送时候
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST; // DMA_DIR_PeripheralSRC; //
DMA_InitStructure.DMA_BufferSize = 0;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(chn, &DMA_InitStructure);
/*
#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008)
#define DMA1_Channel2_BASE (AHBPERIPH_BASE + 0x001C)
#define DMA1_Channel3_BASE (AHBPERIPH_BASE + 0x0030)
#define DMA1_Channel4_BASE (AHBPERIPH_BASE + 0x0044)
#define DMA1_Channel5_BASE (AHBPERIPH_BASE + 0x0058)
#define DMA1_Channel6_BASE (AHBPERIPH_BASE + 0x006C)
#define DMA1_Channel7_BASE (AHBPERIPH_BASE + 0x0080)
*/
if(bInt)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQChannel+((u32)chn-(u32)DMA1_Channel1)/0x14;; //DMAChannel7_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQPreemptionPriority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(chn,DMA_IT_TC,ENABLE);
}
}
void Dma_Rx_Init(DMA_Channel_TypeDef* chn,u32 srcAddr,u8 bInt)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //启动DMA时钟
/* DMA1 Channel7 configuration ----------------------------------------------*/
DMA_DeInit(chn);
DMA_InitStructure.DMA_PeripheralBaseAddr = srcAddr; //(u32)USART2_DR_Address; //外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0; //内存地址,发送时候
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralSRC; // DMA_DIR_PeripheralSRC; //
DMA_InitStructure.DMA_BufferSize = 0;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(chn, &DMA_InitStructure);
if(bInt)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQChannel+((u32)chn-(u32)DMA1_Channel1)/0x14;; //DMAChannel7_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQPreemptionPriority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(chn,DMA_IT_TC,ENABLE);
}
}
void DmaSendData(DMA_Channel_TypeDef* pDmaChnl,INT8U* pSrc,INT32U len)
{
DMA_Cmd(pDmaChnl,DISABLE); //停止使能 才能修改计数器
pDmaChnl->CNDTR=len;
pDmaChnl->CMAR=(INT32U)pSrc;
DMA_Cmd(pDmaChnl,ENABLE); //启动发送
}
INT8U DmaGetData(DMA_Channel_TypeDef* pDmaChnl,INT8U *pDst,INT32U max,INT8U **ppDat)
{
INT8U cnt=0;
DMA_Cmd(pDmaChnl,DISABLE); //停止使能 才能修改计数器
DMA_ClearFlag(DMA_IT_TC<<(((u32)pDmaChnl-(u32)DMA1_Channel1)/5)); //清除传输完成标识
*ppDat=(INT8U*)pDmaChnl->CMAR;
cnt=max-pDmaChnl->CNDTR;
pDmaChnl->CMAR=(INT32U)pDst;
pDmaChnl->CNDTR=max;
DMA_Cmd(pDmaChnl,ENABLE); //启动接收
return cnt;
}
边栏推荐
猜你喜欢
wps a3格式怎么转换成a4?wps a3格式转换成a4的方法
如何搭建一套自己公司的知识共享平台
浅析WLAN——无线局域网
iptables防火墙内容全解
MES docks with Simba to realize IMEI number writing and coupling test of Spreadtrum platform
生活中无处不在的MPLS虚拟专用网
想要精准营销,从学习搭建一套对的标签体系开始丨DTVision分析洞察篇
word文档标题怎么自动编号?
Virtualization type (with picture)
Kubernetes资源编排系列之四: CRD+Operator篇
随机推荐
微信小程序开发一些函数使用方法
JS中数组扁平化的几种方法
wps a列不见了怎么办?wps a列不见了的解决方法
JS中的原型与原型链
Kubernetes 1.25 中的删除和主要变化
免费ARP
面试常问问题之网络整体传输过程
选择排序
按键精灵 for ts API 使用
微信公众号 接口测试平台 获取自定义菜单教程
Free ARP
MySQL 5.5(Windows)的安装教程
win10电脑安装Photoshop cs7软件版本
ArcPy spot number - automatically fill according to field length
微信小程序 wx:for 循环输出 例子
用工具实现 Mock API 的整个流程
有了国产 DevOps 工具 ,还怕数字化转型成本高?
The Socket (Socket)
虚拟化类型(配图)
LeetCode:最长有效括号