您好、TI 社区、
我是新手、我希望通过 DMA 基本模式从 tm4c129EXL 板向1.3英寸 OLED 显示屏连续传输1024位数据。 之前、我尝试以下代码。
使用 uDMA_channel_SSI1TX 通道将数据从缓冲区 g_ui8TxBuf 传输到(void *)(SSI1_base)。 不传输数据
- 我需要 使用 uDMAChannelRequest (uDMA_transfer_channel);来触发还是使用 uDMAChannelEnable (uDMA_transfer_channel);足够了
- 我不确定要在目的地接收数据、我使用的 是 SSIDataGetNonBlocking、这是从 SSI1基地址接收数据的正确方法。
请查找以下代码:
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/ssi.h"
#define CLK_FREQ 80000000
#define CLK_RATE 1000000
#define DATA_WIDTH 8
#define SSI_RXBUF_SIZE 256
#define UDMA_TRANSFER_CHANNEL UDMA_CHANNEL_SSI1TX
#define SSIDATA_FRAME_SIZE UDMA_SIZE_8
#define TIMES_DMA_TRANSFER UDMA_ARB_8
#define UDMA_TRANSFER_MODE UDMA_MODE_BASIC
#define SSI_TXBUF_SIZE 256
unsigned char g_ui8TxBuf[SSI_TXBUF_SIZE];
unsigned char pui8ControlTable[1024];
static unsigned char u32Rxdata[SSI_TXBUF_SIZE];
void init_uDMA();
void config_DMA_transfer();
void spi1_init()
{
unsigned int ui32SysClock;
ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |SYSCTL_OSC_MAIN |SYSCTL_USE_OSC), CLK_FREQ);
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_0);
GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_1);
GPIOPinConfigure(GPIO_PB4_SSI1FSS);
GPIOPinConfigure(GPIO_PB5_SSI1CLK);
GPIOPinConfigure(GPIO_PE4_SSI1XDAT0);
GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_5 | GPIO_PIN_4);
GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_4);
SSIConfigSetExpClk(SSI1_BASE, ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, CLK_RATE, DATA_WIDTH);
SSIEnable(SSI1_BASE);
printf("SPI Iniitiated sh1106 driver\n");
}
int main()
{
spi1_init();
//initialize uDMA module with transfer size of 16 bits
init_uDMA();
config_DMA_transfer();
uint_fast32_t i;
for(i = 0; i < SSI_TXBUF_SIZE; i++)
{
// Wait for data to be available in the receive buffer
while(SSIDataGetNonBlocking(SSI1_BASE, &u32Rxdata[i])) {}
}
//print on console
for(i = 0; i< SSI_TXBUF_SIZE; i++)
{
printf("u32Rxdata[%d] = %d\n", i, u32Rxdata[i]);
}
uDMADisable();
}
//*****************************************************************************
// initiate uDMA module and configure SSI for uDMA transfer
//*****************************************************************************
void init_uDMA()
{
printf("uDMA module initiating\n");
//called once to configure or initiate uDMA
//
// Enable the UDMA peripheral
//
printf("---- Enabling UDMA Peripheral----\n");
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
//
// Wait for the UDMA module to be ready.
//
printf("---- Waiting for UDMA Peripheral to ready----\n");
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))
{
}
uDMAControlBaseSet(&pui8ControlTable[0]);
printf("uDMA channel control base set done\n");
//
// Put the attributes in a known state for the uDMA SSI1TX channel. These
// should already be disabled by default.
//
uDMAChannelAttributeDisable(UDMA_TRANSFER_CHANNEL,UDMA_ATTR_ALTSELECT |
UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
//
// Set the USEBURST attribute for the uDMA SSI TX channel. This will
// force the controller to always use a burst when transferring data from
// the TX buffer to the UART. This is somewhat more efficient bus usage
// than the default which allows single or burst transfers.
//
uDMAChannelAttributeEnable(UDMA_TRANSFER_CHANNEL, UDMA_ATTR_USEBURST);
printf("uDMA channel attributes set done\n");
uDMAChannelControlSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
SSIDATA_FRAME_SIZE | UDMA_SRC_INC_8 |
UDMA_DST_INC_NONE | TIMES_DMA_TRANSFER);
printf("uDMA channel control set is done\n");
//enabling the uDMA module
uDMAEnable();
//
// Enable the uDMA interface for TX channel.
//
//
SSIDMAEnable(SSI1_BASE, SSI_DMA_TX); // transfer the control to uDMA controller
}
void config_DMA_transfer()
{
printf("SSI1 Transfering\n");
static uint_fast16_t ui16Idx;
//
// Fill the TX buffer with a simple data 0 to 255.
//
for(ui16Idx = 0; ui16Idx < SSI_TXBUF_SIZE; ui16Idx++)
{
g_ui8TxBuf[ui16Idx] = ui16Idx;
printf("g_ui8TxBuf %d\n", g_ui8TxBuf[ui16Idx]);
}
printf("DMA Transfer enabled\n");
//
// Set up the transfer parameters for the uDMA SSI TX channel. This will
// configure the transfer source and destination and the transfer size.
// Basic mode is used because the peripheral is making the uDMA transfer
// request. The source is the TX buffer and the destination is the SSI
// data register.
//
// Not transfering data from tx to SSI Base
uDMAChannelTransferSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
UDMA_TRANSFER_MODE, g_ui8TxBuf,
(void *)(SSI1_BASE),
sizeof(g_ui8TxBuf));
uDMAChannelEnable(UDMA_TRANSFER_CHANNEL);
printf("uDMA transfer channel enabled\n");
printf("--- Waiting to complete data transfer ---\n");
//wait for DMA transfer to complete
while(uDMAChannelIsEnabled(UDMA_TRANSFER_CHANNEL)) {}
printf("\n--- Transfer completed ---\n");
}
提前感谢您