山景BP1048 GPIO通过DMA方式输出

该代码段展示了如何在嵌入式系统中初始化LED通路资源,使用DMA和定时器进行数据传输。它定义了与GPIO端口、定时器寄存器相关的常量,并设置了一个大型的数据缓冲区用于DMA传输。通过数据转换函数将RGB值转化为适合DMA传输的格式,并通过`data_send`函数处理并发送数据到DMA通道。

 数据定义

//音频通路资源初始化
#define LED_BUFFER_LEN		(8*4*3*18)//8*4*3*3 + 800//1024
#define	ADR_GPIO_A_REG_O	(0x40010004+3)
#define	REG_TIMER4_CTRL		(*(volatile unsigned long *) 0x4002C800)
#define	REG_TIMER4_NUM		(*(volatile unsigned long *) 0x4002C80C)
//#define gpio_a20             1<<4
#define RGB_LED_NUM 18//126

uint32_t rgb_buf[3*RGB_LED_NUM];

#ifndef CFG_MORE_GPIO_RGB_CTRL_EN
#define LED_PORT		LED_GPIO1	//1<<4
#define	LED_GPIO1		1<<4

typedef struct{
	uint8_t rgb_pwm_cnt;
	uint8_t buf[32];//
#ifdef CFG_MORE_GPIO_RGB_CTRL_EN
	uint8_t buf1[32];
#endif
//	int8_t buf_bak[RGB_LED_NUM];
}RGB_ST;

 RGB_ST RGB_R;
 RGB_ST RGB_G;
 RGB_ST RGB_B;


uint8_t  DmaTestBuffer[LED_BUFFER_LEN]=
{
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//1
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//2
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//3
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//4
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//5
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//6

	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
 //7
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//8
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//9
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//10
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//11
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
 //12
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//13
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//14
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//15 
    LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//16

	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
//17
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
	LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,LED_PORT,0,0,0,
};  



初始化

/*
*********************************************************
*				IO口和DMA通道初始化
*********************************************************
*/
void Led_Dma_Proc_Init(void)
{
	DMA_CONFIG DMAConfig;
	uint32_t DmaTestLen;
	memset(DmaTestBuffer,0,sizeof(DmaTestBuffer));
	GPIO_RegOneBitClear(GPIO_A_IE, GPIOA28);
	GPIO_RegOneBitSet(GPIO_A_OE, GPIOA28);

	DmaTestLen = LED_BUFFER_LEN;//LED_BUFFER_LEN*4;
	DMAConfig.Dir = DMA_CHANNEL_DIR_MEM2PERI;
	DMAConfig.Mode = DMA_BLOCK_MODE; //DMA_CIRCULAR_MODE;
	DMAConfig.SrcAddress = (uint32_t)DmaTestBuffer;
	DMAConfig.SrcDataWidth = DMA_SRC_DWIDTH_BYTE;
	DMAConfig.SrcAddrIncremental = DMA_SRC_AINCR_SRC_WIDTH;
	DMAConfig.DstAddress = ADR_GPIO_A_REG_O;

	GPIO_RegBitsSet(GPIO_A_DMA_OUT_MASK, (~(GPIO_INDEX28)));

	DMAConfig.DstDataWidth =  DMA_DST_DWIDTH_BYTE;
	DMAConfig.DstAddrIncremental = DMA_DST_AINCR_NO;
	DMAConfig.BufferLen = DmaTestLen;
	DMA_TimerConfig(PERIPHERAL_ID_TIMER4, &DMAConfig);
	DMA_BlockConfig(PERIPHERAL_ID_TIMER4);
	DMA_BlockBufSet(PERIPHERAL_ID_TIMER4,DmaTestBuffer,DmaTestLen);
	//DMA_CircularWritePtrSet(PERIPHERAL_ID_TIMER4, DmaTestLen+16);//将写指针指向buffer外
	DMA_ChannelEnable(PERIPHERAL_ID_TIMER4);
	Timer_Config(TIMER4, 1, 0);
	REG_TIMER4_NUM = 47;//41;//
	Timer_Start(TIMER4);
	REG_TIMER4_CTRL |= (1<<8);
}

 数据转换和发送数据接口

/*
///////////////////////////////////////////////////////////////////
//						数据转换函数1							 //
///////////////////////////////////////////////////////////////////
*/
uint32_t rgb_data_change(uint8_t data)	//24 = 3*8
{
	uint32_t data_u32 = 0;
    uint8_t i;
	for(i = 0;i<8;i++){
		// 1 --> 1110   0--> 1000
		if(data & BIT(7)){
			data_u32 = data_u32 | (0x0e);
		}else{
			data_u32 = data_u32 | (0x08);
		}
		data <<= 1;
		if(i < 7){
			data_u32 <<= 4;
		}
	}
	return data_u32;
}

/*
******************************************************
*				将数据传送到DMA通道中
******************************************************
*/
void DmaDataChange1(void)
{
	uint32_t TempData;
	uint16_t i, j;

   for(i=0;i<54;i++)
   {
		for(j=0;j<32;j++)
		{
			TempData = 0;
			if(rgb_buf[i] &  BIT(31-j)){
				TempData = LED_GPIO1;//TempData = LED_PORT;
			}
			DmaTestBuffer[ i*32+j] =(uint8_t) TempData;
		}
  }
}

/*
///////////////////////////////////////////////////////////////////
//						数据转换函数2							 //
///////////////////////////////////////////////////////////////////
*/
void rgb_data_deal(void)
{
	uint32_t g_data_32,r_data_32,b_data_32 = 0;
    uint8_t i;

    g_data_32 = 0;
	r_data_32 = 0;
	b_data_32 = 0;
	for( i = 0;i< RGB_LED_NUM;i++){

        r_data_32 = rgb_data_change(RGB_R.buf[i]);
        g_data_32 = rgb_data_change(RGB_G.buf[i]);
        b_data_32 = rgb_data_change(RGB_B.buf[i]);
        rgb_buf[i*3] = g_data_32;
        rgb_buf[i*3+1] =  r_data_32;
        rgb_buf[i*3+2] = b_data_32;
	}
}


void data_send(unsigned char * pstr, unsigned char nbr)
{
	uint8_t i = 0;
	for(i = 0; i < 18; i++)
	{
		RGB_R.buf[i] = pstr[i * 3 + 0];
		RGB_G.buf[i] = pstr[i * 3 + 1];
		RGB_B.buf[i] = pstr[i * 3 + 2];
	}
	rgb_data_deal();
	DmaDataChange1();

	DMA_InterruptFlagClear(PERIPHERAL_ID_TIMER4,DMA_DONE_INT);
	Timer_InterruptFlagClear(TIMER4,UPDATE_INTERRUPT_SRC);
	Timer_Pause(TIMER4,1);
	DMA_ChannelDisable(PERIPHERAL_ID_TIMER4);
	DMA_BlockBufSet(PERIPHERAL_ID_TIMER4,DmaTestBuffer,LED_BUFFER_LEN);
	DMA_ChannelEnable(PERIPHERAL_ID_TIMER4);
	Timer_Pause(TIMER4,0);
}

### 山景 BP1048 开发环境配置与设置 #### 1. 开发环境概述 山景 BP1048 是一款基于 BLE 技术的开发板,其硬件设计和软件开发均需特定工具链的支持。为了顺利开展项目开发工作,开发者需要完成一系列必要的准备工作。 #### 2. 软件安装与环境搭建 对于 BP1048 的开发环境,通常建议按照以下方式构建: - **SDK 下载**: 官方 SDK 提供了完整的驱动库和支持文档。开发者可以从官网下载最新版本的 SDK 并解压至本地目录[^3]。 - **Flash 工具**: 烧录固件所需的 Flash 工具位于 `\MVsB1_Base_SDK\tools` 文件夹下。具体来说,`b1_download_v1.3.exe` 是用于烧录的主要工具。该工具可以直接复制到当前工程的 `release/output` 文件夹中以便于操作[^3]。 - **IDE 支持**: 推荐使用 Keil 或 IAR Embedded Workbench 进行代码编辑、调试和编译。这些 IDE 可以为用户提供友好的界面以及强大的调试功能。 #### 3. 硬件接口初始化 BP1048 的硬件接口初始化是一个重要的环节,尤其是针对 I2C 总线的操作。以下是典型的 I2C 初始化函数实现: ```c void I2C_GPIO_Init(void) { GPIO_PortBModeSet(GPIOB4, 0); GPIO_RegOneBitSet(GPIO_B_OE, GPIOB4); GPIO_RegOneBitClear(GPIO_B_IE, GPIOB4); GPIO_PortBModeSet(GPIOB5, 0); GPIO_RegOneBitSet(GPIO_B_OE, GPIOB5); GPIO_RegOneBitClear(GPIO_B_IE, GPIOB5); GPIO_RegOneBitSet(GPIO_B_PU, GPIOB4); GPIO_RegOneBitClear(GPIO_B_PD, GPIOB4); GPIO_RegOneBitSet(GPIO_B_PU, GPIOB5); GPIO_RegOneBitClear(GPIO_B_PD, GPIOB5); I2C_Init(0x28, I2C_PORT_B4_B5, B1X_ADDR); DelayMs(1000); } ``` 此代码片段展示了如何通过 GPIO 配置 SDA 和 SCL 引脚,并调用 `I2C_Init()` 函数来启动总线通信[^4]。 #### 4. 测试与验证 在完成上述配置之后,可以通过编写简单的测试程序来验证开发环境的功能性。例如,尝试读取或写入某个已知地址上的寄存器数据,以此确认硬件连接正常并能正确响应命令。 --- ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值