STM32F030F4P6控制WS2811灯带

1、STM32F030使用的是内部晶振,频率48MHZ。刚开始根据网上资料想用IO模拟时序发现没有预期显示效果。后期又用定时器PWM模式加DMA模式实现WS2811芯片的控制。STM32是3.3V供电,WS2811是5V脉冲。所以采用一个SN74LVC2T45DCUR(SN74LVC2T45 具有可配置电压转换的 双位双电源总线收发器)转换频率可达到420Mbps(3.3V 至 5V 转换)。STM32F030F4P6可以直接用定时器3的CH1(PA6)口,我当时没考虑这块随便弄了PA4和PA3,这就导致我在程序里配置DMA的时候又重新映射了一下,定时器没有配置成外部输出,改成内部事件了(TIM_OCMode_Timing)。原理图如下:

2、了解下WS2811的性质,基础知识资料很多可以对应搜索,他需要1.25us时钟,根据占空比来确定0 1,比如高电平占350ns时表示0,高电平占700ns时表示1。如图所示:

那就要求STM32F030先配个定时器实现PWM可调,那就程序配置预分频TIM_Prescaler为0,TIM_Period 计数59。这样就是T=(TIM_Period+1)*(TIM_Prescaler+1)/TIMxCLK,1*60/48000000=1.25us。用逻辑分析仪检测脉冲TIM_Pulse计数是17时高电平是350ns,脉冲TIM_Pulse计数是34时高电平是700ns,用逻辑分析仪监控了一段WS2811的数据RGB分别8位总共是24位。这是显示绿色的脉冲如图所示:

3、复制相关代码:

48M内部时钟开启:
void SystemClock_Config(void)
{
    RCC_DeInit();
    FLASH_SetLatency(FLASH_Latency_1);
    RCC_HSICmd(ENABLE);

    while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) != SET);

    RCC_AdjustHSICalibrationValue(16);
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_12);
    RCC_PLLCmd(ENABLE);

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);

    RCC_HCLKConfig(RCC_SYSCLK_Div1);
    RCC_PCLKConfig(RCC_HCLK_Div1);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    while (RCC_GetSYSCLKSource() != 0x08)
    {
    }

    RCC_USARTCLKConfig(RCC_USART1CLK_PCLK);
}	


extern __O uint8_t WS2811_IO_High;    //PA3 PA4    
extern __O uint8_t WS2811_IO_Low ;    //PA3 PA4
extern uint8_t WS2811_IO_FrameData[264];     //11节RGB
void OUT_GPIO_Init(void)
	{
		GPIO_InitTypeDef  GPIO_InitStructure;
		
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//
		
		GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;          //PA6控制485通信 接收发送
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;     //普通输出模式
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
		GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;       
		GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO	
		
		GPIO_ResetBits(GPIOA,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6);               //设置0
	}
	
	void WS2811_Init_Timer(void)
	{
		TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
		TIM_OCInitTypeDef TIM_OCInitStructure;
		NVIC_InitTypeDef NVIC_InitStructure;

		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

		TIM_TimeBaseStructure.TIM_ClockDivision = 0;
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
		TIM_TimeBaseStructure.TIM_Prescaler = 0;
		TIM_TimeBaseStructure.TIM_Period = 59;
		TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

		TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
		TIM_ARRPreloadConfig(TIM3, DISABLE);

		TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
		TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
		TIM_OCInitStructure.TIM_Pulse = 17;
		TIM_OC1Init(TIM3, &TIM_OCInitStructure);
		TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);   //立即生效

		TIM_OCInitStructure.TIM_Pulse = 34;
		TIM_OC3Init(TIM3, &TIM_OCInitStructure);
		TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);   //立即生效

		NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);
	}
	
	void WS2811_Init_DMA(void)
	{
		DMA_InitTypeDef DMA_InitStructure;
		NVIC_InitTypeDef NVIC_InitStructure;

		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

		// TIM3 update event, DMA1 Channel 3
		DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOA->ODR;
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&WS2811_IO_High;
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                      //外设作为数据传输的目的地
		DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
		DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
		DMA_InitStructure.DMA_BufferSize = 0;                                   // 
		DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
		DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;                //DMA存储地址不递增
		DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
		DMA_InitStructure.DMA_Priority = DMA_Priority_High;
		DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
		DMA_Init(DMA1_Channel3, &DMA_InitStructure);

		// TIM3 CC1 event, DMA1 Channel 4
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)WS2811_IO_FrameData; //WS2812B_IO_FrameData[0];
		DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                //DMA存储地址递增
		DMA_Init(DMA1_Channel4, &DMA_InitStructure);

		// TIM3 CC3 event, DMA1 Channel 2
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&WS2811_IO_Low;
		DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;              //DMA存储地址不递增
		DMA_Init(DMA1_Channel2, &DMA_InitStructure);

		// DMA1 Channel 2 interrupt
		NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);

		DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
	}


void WS2811::WS2811_Send_Buffer(void)
{
	WS2811_TC = 0;

	DMA_ClearFlag(DMA1_FLAG_TC2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2 | DMA1_FLAG_TE2);
	DMA_ClearFlag(DMA1_FLAG_TC3 | DMA1_FLAG_HT3 | DMA1_FLAG_GL3 | DMA1_FLAG_TE3);
	DMA_ClearFlag(DMA1_FLAG_TC4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4 | DMA1_FLAG_TE4);

	DMA_SetCurrDataCounter(DMA1_Channel2, WS2811_BUFFER_SIZE);      
	DMA_SetCurrDataCounter(DMA1_Channel3, WS2811_BUFFER_SIZE);       
	DMA_SetCurrDataCounter(DMA1_Channel4, WS2811_BUFFER_SIZE);      

	TIM3->SR = 0;

	DMA_Cmd(DMA1_Channel2, ENABLE);
	DMA_Cmd(DMA1_Channel3, ENABLE);
	DMA_Cmd(DMA1_Channel4, ENABLE);

	TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);
	TIM_DMACmd(TIM3, TIM_DMA_CC3, ENABLE);
	TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);

	TIM_SetCounter(TIM3, 60);

	TIM_Cmd(TIM3, ENABLE);
}

uint8_t WS2811::WS2811_Get_TC(void)
{
	return WS2811_TC;
}




主函数:
__O uint8_t WS2811_IO_High = 0x18;    //PA3 PA4    
__O uint8_t WS2811_IO_Low  = 0xE7;    //PA3 PA4
uint8_t WS2811_IO_FrameData[264];     //11节RGB
__IO uint8_t WS2811_TC = 1;           //WS2811发送完毕 
uint16_t WS2811_BUFFER_SIZE = 264;   //11节RGB
//11段RGB灯带控制
__IO uint8_t WS2811_IO_FrameDataR[264]=
{
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
	17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
};
__IO uint8_t WS2811_IO_FrameDataG[264]=
{
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,
	34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,34,34,34,34,34,34,34,34,	
};
__IO uint8_t WS2811_IO_FrameDataB[264]=
{ 
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
	34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,17,17,17,17,17,17,17,17,
};

int main(void)
{
	uint8_t i;
	SystemClock_Config();
	OUT_GPIO_Init();
	My_Uart1.Begin(1,9600);
	WS2811_Init_Timer();
    WS2811_Init_DMA();
	TIM17_Config();
    CTRL=0;	                 //模块处于接收模式
	delay_ms(200);
  	strcpy((char*) WS2811_IO_FrameData,(char*) WS2811_IO_FrameDataB);  //开机发送蓝色
    RGB_WS2811.WS2811_Send_Buffer();
	delay_ms(200);
	while(1)
	{
		MyU1CmdProcess();
	}
}

对应的中断处理
	void DMA1_Channel2_3_IRQHandler(void)
	{
		DMA_ClearITPendingBit(DMA1_IT_TC2);
		GPIO_ResetBits(GPIOA,GPIO_Pin_3|GPIO_Pin_4);//设置0
		TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

		DMA_Cmd(DMA1_Channel2, DISABLE);
		DMA_Cmd(DMA1_Channel3, DISABLE);
		DMA_Cmd(DMA1_Channel4, DISABLE);

		TIM_DMACmd(TIM3, TIM_DMA_CC1, DISABLE);
		TIM_DMACmd(TIM3, TIM_DMA_CC3, DISABLE);
		TIM_DMACmd(TIM3, TIM_DMA_Update, DISABLE);
	}

	void TIM3_IRQHandler(void)
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
		TIM_Cmd(TIM3, DISABLE);
		TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
		WS2811_TC = 1;
	}

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值