STM32平台下的TM1812驱动
TM1812芯片的特性如下:
数据传输参数及时序:
在上图中一个串联了三个TM1812芯片,每个芯片控制四盏灯,每盏灯有R,G,B三种颜色,每种颜色有256(0xFF)阶灰度可调,及每个颜色用一个字节控制。发送完全部LED灯的数据后,发送RESET信号进行LED显示以及重新接收数据。
下面是我在STM32F030C8T6中的驱动,时钟频率48MHz。
tm1812.h的代码:
#ifndef __LED_TM1812_H__
#define __LED_TM1812_H__ /* Define macro __LED_TM1812_H__ */#ifdef __cplusplus
extern "C"{
#endif#include <stdint.h>#define TM1812_CHIP_NUMBER (8) /* TM1812 chip number */
#define ONE_RESOLUTION_SIZE (TM1812_CHIP_NUMBER*4*3) /* A row RGB LED bytes size, a TM1812 chip control 4 LEDs, a LED contain 3 bytes(R,G,B)*//* Data input channel */
typedef enum
{DIN1,DIN2,DIN3,DIN4,
}DIN_t;/* Unipolar Return-to-zero code default low level, code 1, 1.25us */
#define DIN_BIT_1(GPIO_Type, GPIO_Pin) do \{ \GPIO_Type->BSRR = GPIO_Pin; \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP(); \GPIO_Type->BRR = GPIO_Pin; \__NOP();__NOP();__NOP(); \}while(0)/* Unipolar Return-to-zero code default low level, code 0, 1.25us */
#define DIN_BIT_0(GPIO_Type, GPIO_Pin) do \{ \GPIO_Type->BSRR = GPIO_Pin; \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP(); \GPIO_Type->BRR = GPIO_Pin; \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP();__NOP();__NOP();__NOP(); \__NOP(); \}while(0)void TM1812_LEDInit(void);
void TM1812_DataPowerOn(void);
void TM1812_DataPoweOff(void);
int TM1812_WriteOneByte(DIN_t Din, uint8_t Data);
int TM1812_Reset(DIN_t Din);
int TM1812_TransmitData(DIN_t Din, const uint8_t* Data, uint32_t Size);
void TM1812_Test(void);#ifdef __cplusplus
}
#endif#endif /* End define macro __LED_TM1812_H__ */
tm1812.c代码:
#include "stm32f0xx_hal.h"
#include "led_tm1812.h"
#include "usart.h"
#include <string.h>
#include "cmsis_os.h"
#include <stdbool.h>/*
** @Brief: execute nCount no operation, delay a short time
** @Parameters: us, delay us
** @Return: None
**/
static void DelayUs(uint32_t nUs)
{uint32_t Index = 0;uint32_t TmpIndex = 0;for(Index = 0; Index < nUs; Index++){for(TmpIndex = 0; TmpIndex < 7; TmpIndex++){__NOP();}}
}/*
** @Brief: Init RGBLED tm1812 relative pins
** @Parameters: None
** @Return: None
**/
void TM1812_LEDInit(void)
{/* * DIN1 ---> PB4 (Output)* DIN2 ---> PB5 (Output)* DIN3 ---> PB10 (Output)* DIN4 ---> PB2 (Output)* LED_EN1 ---> PB6 (Output)*/GPIO_InitTypeDef GPIO_InitStruct;/* GPIO Clock Enable */__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pins : PB2 PB10 PB4 PB5 */GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_10 | GPIO_PIN_4 | GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLDOWN;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/*Configure GPIO pins : PB6 */GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* Configure GPIO pin default Output Level *//* DIN1, DIN2, DIN3, DIN4 default is low level */HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_10, GPIO_PIN_RESET);/* Power off TM1812 */HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
}/*
** @Brief: Enable data input
** @Parameter: None
** @Return: None
**/
void TM1812_PowerOn(void)
{/** LED_EN1 ---> PB6 (Output)*/HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
}/*
** @Brief: Disable data input
** @Parameter: None
** @Return: None
**/
void TM1812_PowerOff(void)
{/** LED_EN1 ---> PB6 (Output)*/HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
}/*
** @Brief: Data transmit is used unipolar return to zero code
** @Parameter: 1) Din, select data input port2) Data, one byte data that would be transmitted
** @Return: 1) 0, transmit successful2) -1, data input port error
**/
int TM1812_WriteOneByte(DIN_t Din, uint8_t Data)
{int BitIndex = 0;switch(Din){case DIN1:for(BitIndex = 8*sizeof(Data)-1; BitIndex >= 0; BitIndex--){if(Data & (0x01 << BitIndex)){DIN_BIT_1(GPIOB, GPIO_PIN_4);}else{DIN_BIT_0(GPIOB, GPIO_PIN_4);}}break;case DIN2:for(BitIndex = 8*sizeof(Data)-1; BitIndex >= 0; BitIndex--){if(Data & (0x01 << BitIndex)){DIN_BIT_1(GPIOB, GPIO_PIN_5);}else{DIN_BIT_0(GPIOB, GPIO_PIN_5);}}break;case DIN3:for(BitIndex = 8*sizeof(Data)-1; BitIndex >= 0; BitIndex--){if(Data & (0x01 << BitIndex)){DIN_BIT_1(GPIOB, GPIO_PIN_10);}else{DIN_BIT_0(GPIOB, GPIO_PIN_10);}}break;case DIN4:for(BitIndex = 8*sizeof(Data)-1; BitIndex >= 0; BitIndex--){if(Data & (0x01 << BitIndex)){DIN_BIT_1(GPIOB, GPIO_PIN_2);}else{DIN_BIT_0(GPIOB, GPIO_PIN_2);}}break;default:return -1;}return 0;
}/*
** @Brief: Send a reset signal
** @Parameter: Din, select data input port
** @Return: 1) 0, send a reset signal successful2) -1, data input port error
**/
int TM1812_Reset(DIN_t Din)
{switch(Din){case DIN1:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); DelayUs(24);break;case DIN2:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); DelayUs(24);break;case DIN3:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); DelayUs(24);break;case DIN4:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); DelayUs(24);break;default:return -1;}return 0;
}/*
** @Brief: Transmit LED data
** @Parameter: 1) Din, data input port2) Data, transmit data3) Size, data size
** @Return: 1) 0, transmit data successful2) -1, data is null or data size illegal
**/
int TM1812_TransmitData(DIN_t Din, const uint8_t* Data, uint32_t Size)
{int ByteIndex = 0;if((NULL == Data) || (Size != ONE_RESOLUTION_SIZE)){return -1;}/* Disable all maskable interrupts */taskDISABLE_INTERRUPTS();for(ByteIndex = 0; ByteIndex < Size; ByteIndex++){TM1812_WriteOneByte(Din, Data[ByteIndex]);}/* Enable microcontroller interrupts */taskENABLE_INTERRUPTS(); TM1812_Reset(Din);return 0;
}/*
** Brief: Test Led only
**/
void TM1812_Test(void)
{uint8_t Data[ONE_RESOLUTION_SIZE] = {0};uint32_t DataSize = sizeof(Data) / sizeof(Data[0]);int DataIndex = 0;static int ColorFlag = 1;if(ColorFlag > 3){ColorFlag = 1;}memset(Data, 0, DataSize);for(DataIndex = 0; DataIndex < DataSize; DataIndex++){if(1 == ColorFlag) /* Red */{if(((DataIndex+1) % 3) != 1){Data[DataIndex] = 0x00;}else{Data[DataIndex] = 0xFF;}}else if(2 == ColorFlag) /* Green */{if(((DataIndex+1) % 3) != 2){Data[DataIndex] = 0x00;}else{Data[DataIndex] = 0xFF;}}else if(3 == ColorFlag) /* Blue */{if(((DataIndex+1) % 3) != 0){Data[DataIndex] = 0x00;}else{Data[DataIndex] = 0xFF;}}TM1812_TransmitData(DIN1, Data, DataSize);TM1812_TransmitData(DIN2, Data, DataSize);TM1812_TransmitData(DIN3, Data, DataSize);TM1812_TransmitData(DIN4, Data, DataSize);}memset(Data, 0, DataSize);for(DataIndex = DataSize - 1; DataIndex >= 0; DataIndex--){if(1 == ColorFlag) /* Red */{if(((DataIndex+1) % 3) != 1){Data[DataIndex] = 0x00;}else{Data[DataIndex] = 0xFF;}}else if(2 == ColorFlag) /* Green */{if(((DataIndex+1) % 3) != 2){Data[DataIndex] = 0x00;}else{Data[DataIndex] = 0xFF;}}else if(3 == ColorFlag) /* Blue */{if(((DataIndex+1) % 3) != 0){Data[DataIndex] = 0x00;}else{Data[DataIndex] = 0xFF;}}TM1812_TransmitData(DIN1, Data, DataSize);TM1812_TransmitData(DIN2, Data, DataSize);TM1812_TransmitData(DIN3, Data, DataSize);TM1812_TransmitData(DIN4, Data, DataSize);}ColorFlag++;
}
说明:该驱动程序连接了四排LED,每排串联了8个TM1812芯片,故分成了四个数据通道。
总结:TM1812适合做静态光源,不适合做动态显示,动态显示会出现不同芯片数据显示不同步(断层)现象。因为TM1812数据传输采取的是单极性归零码传输,是一种单线传输,芯片之间没有时钟线进行数据同步,数据线默认状态是低电平,而且在一定时间(大于8us)内没有传输数据就会自动复位,进入重新接收数据的状态,因此刷新频率较高并且在运动时,芯片之间数据不同步现象会非常明显。
STM32平台下的TM1812驱动相关推荐
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的I2C驱动架构分析
PowerPC + Linux2.6.25平台下的I2C驱动架构分析 Sailor_forever sailing_9806#163.com (本原创文章发表于Sailor_forever 的个人b ...
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析
PowerPC + Linux2.6.25平台下的SPI驱动架构分析 Sailor_forever sailing_9806#163.com (本原创文章发表于Sailor_forever 的个人b ...
- FreeScale mpc8xxx + vxWorks平台下spi flash驱动开发三步走
最近在弄PowerPC平台上的spi flash的驱动程序,总体比较简单,在借鉴了U-Boot中的相关源码后,花了两周左右的时间搞定了,对于spi总线之前一直都有了解,但未能实际接触,这次在vxWor ...
- linux 音频驱动的流程,Intel平台下Linux音频驱动流程分析
[软件框架] 在对要做的事情一无所知的时候,从全局看看系统的拓扑图对我们认识新事物有很大的帮助.Audio 部分的驱动程序框架如下图所示: 这幅图明显地分为 3 级. 上方蓝色系的 ALSA Kern ...
- 安卓平台下的GPS架构介绍及驱动移植记录
一.前言 我的工作是关于汽车车机BSP部分. 汽车车机,其实基本和人们日常所用的手机一样,也是安卓平台的.所谓安卓,就是一层安卓服务包裹着Linux内核所形成的操作系统. BSP组,主要工作内容就是负 ...
- BEA WebLogic平台下J2EE调优攻略--转载
BEA WebLogic平台下J2EE调优攻略 2008-06-25 作者:周海根 出处:网络 前 言 随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供 ...
- ElasticSearch-.net平台下c#操作ElasticSearch详解
ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...
- Android L系统mtk平台下AAL自动背光调整服务亮度曲线调试需要涉及的地方
Android L系统mtk平台下AAL自动背光调整服务亮度曲线调试需要涉及的地方 如果你想修改MTK的AAL自动背光调整相关的内容,那么根据情况,可能需要涉及如下文件: 这是Android L版本的 ...
- Win10 平台下, LightGBM GPU 版本的安装
1. Light GBM 简介 在数据挖掘和传统机器学习领域,提起大名鼎鼎的 XGBoost,相信很多人都听说过,尤其是在 Kaggle 赛场上,XGBoost 更是风光无限,不过今天的主角却不是 X ...
- U8G2库移植到STM32平台上
U8G2库简介 U8g2是嵌入式设备的单色图形库,一句话简单明了.主要应用于嵌入式设备,包括我们常见的单片机: 建议先看这篇博客的介绍,写的比较好u8g2库的使用 这篇博客介绍了对于u8g2的使用,但 ...
最新文章
- smartupload 上传文件时 把页面编码改成gbk 解决乱码
- 新闻行业中,自然语言理解技术该如何应用?
- 第21章:MongoDB-聚合操作--聚合管道--$geoNear
- Caffe下自己的数据训练和测试
- jQuery easyUI--tabs选项卡面板
- C++起始(内联函数,宏的优缺点,const关键字,auto关键字(C++11)基于范围的for循环(C++11). 指针空值nullptr(C++11))
- php div边框,CSS自定义边框
- 在c51语言的程序中 注释一般采用,【判断题】在 C51 语言的程序中,注释一般采用 /* */ 和 // 来实现。 (3.0分)...
- 推荐一些vue.js热门好用的框架组件
- SpaceX 火箭发射成功,一文了解所用的软件技术栈!
- Underscore js是一个JavaScript实用库
- 应广单片机(MCU单片机科普)
- 版本控制工具-Git
- 弱电从业人员必须学习的一些CAD绘图技巧
- 【IP路由基础(直连路由、静态路由的三种配置)】--20211203、20211206
- Java中implement和extend
- mybatipse 下载_哇塞!可以免费下载某度文档的doc格式啦
- 简单Java Web 开发:Eclipse+Struts2+Tomcat+MySQL(workbench)+SAE
- win10装系统输入用户名就卡死
- Apollo6.0_ReferenceLine_Smoother解析与子方法对比
热门文章
- qt实现拓扑图_基于QT的PLC梯形图编辑系统设计与实现
- Early stopping conditioned on metric `acc` which is not available. Available metrics are: loss,val_l
- python往word文档中写入表格、段落、标题、图片...(超级全)
- win10计算机上的策略禁止用户安装,win10电脑安装摄像头驱动时提示策略禁止安装此设备的解决教程...
- 永不消逝的电波-wirteup
- Android studio添加依赖是什么意思以及添加依赖的方法
- java2048移动算法_2048游戏通关算法
- 网页中使用iconfont图标
- 春运抢火车票攻略汇总(持续更新中)
- Discuz!风格模版初级不完全修改教程