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驱动相关推荐

  1. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的I2C驱动架构分析

    PowerPC + Linux2.6.25平台下的I2C驱动架构分析 Sailor_forever  sailing_9806#163.com (本原创文章发表于Sailor_forever 的个人b ...

  2. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析

    PowerPC + Linux2.6.25平台下的SPI驱动架构分析 Sailor_forever  sailing_9806#163.com (本原创文章发表于Sailor_forever 的个人b ...

  3. FreeScale mpc8xxx + vxWorks平台下spi flash驱动开发三步走

    最近在弄PowerPC平台上的spi flash的驱动程序,总体比较简单,在借鉴了U-Boot中的相关源码后,花了两周左右的时间搞定了,对于spi总线之前一直都有了解,但未能实际接触,这次在vxWor ...

  4. linux 音频驱动的流程,Intel平台下Linux音频驱动流程分析

    [软件框架] 在对要做的事情一无所知的时候,从全局看看系统的拓扑图对我们认识新事物有很大的帮助.Audio 部分的驱动程序框架如下图所示: 这幅图明显地分为 3 级. 上方蓝色系的 ALSA Kern ...

  5. 安卓平台下的GPS架构介绍及驱动移植记录

    一.前言 我的工作是关于汽车车机BSP部分. 汽车车机,其实基本和人们日常所用的手机一样,也是安卓平台的.所谓安卓,就是一层安卓服务包裹着Linux内核所形成的操作系统. BSP组,主要工作内容就是负 ...

  6. BEA WebLogic平台下J2EE调优攻略--转载

    BEA WebLogic平台下J2EE调优攻略   2008-06-25 作者:周海根 出处:网络   前 言 随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供 ...

  7. ElasticSearch-.net平台下c#操作ElasticSearch详解

    ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...

  8. Android L系统mtk平台下AAL自动背光调整服务亮度曲线调试需要涉及的地方

    Android L系统mtk平台下AAL自动背光调整服务亮度曲线调试需要涉及的地方 如果你想修改MTK的AAL自动背光调整相关的内容,那么根据情况,可能需要涉及如下文件: 这是Android L版本的 ...

  9. Win10 平台下, LightGBM GPU 版本的安装

    1. Light GBM 简介 在数据挖掘和传统机器学习领域,提起大名鼎鼎的 XGBoost,相信很多人都听说过,尤其是在 Kaggle 赛场上,XGBoost 更是风光无限,不过今天的主角却不是 X ...

  10. U8G2库移植到STM32平台上

    U8G2库简介 U8g2是嵌入式设备的单色图形库,一句话简单明了.主要应用于嵌入式设备,包括我们常见的单片机: 建议先看这篇博客的介绍,写的比较好u8g2库的使用 这篇博客介绍了对于u8g2的使用,但 ...

最新文章

  1. smartupload 上传文件时 把页面编码改成gbk 解决乱码
  2. 新闻行业中,自然语言理解技术该如何应用?
  3. 第21章:MongoDB-聚合操作--聚合管道--$geoNear
  4. Caffe下自己的数据训练和测试
  5. jQuery easyUI--tabs选项卡面板
  6. C++起始(内联函数,宏的优缺点,const关键字,auto关键字(C++11)基于范围的for循环(C++11). 指针空值nullptr(C++11))
  7. php div边框,CSS自定义边框
  8. 在c51语言的程序中 注释一般采用,【判断题】在 C51 语言的程序中,注释一般采用 /* */ 和 // 来实现。 (3.0分)...
  9. 推荐一些vue.js热门好用的框架组件
  10. SpaceX 火箭发射成功,一文了解所用的软件技术栈!
  11. Underscore js是一个JavaScript实用库
  12. 应广单片机(MCU单片机科普)
  13. 版本控制工具-Git
  14. 弱电从业人员必须学习的一些CAD绘图技巧
  15. 【IP路由基础(直连路由、静态路由的三种配置)】--20211203、20211206
  16. Java中implement和extend
  17. mybatipse 下载_哇塞!可以免费下载某度文档的doc格式啦
  18. 简单Java Web 开发:Eclipse+Struts2+Tomcat+MySQL(workbench)+SAE
  19. win10装系统输入用户名就卡死
  20. Apollo6.0_ReferenceLine_Smoother解析与子方法对比

热门文章

  1. qt实现拓扑图_基于QT的PLC梯形图编辑系统设计与实现
  2. Early stopping conditioned on metric `acc` which is not available. Available metrics are: loss,val_l
  3. python往word文档中写入表格、段落、标题、图片...(超级全)
  4. win10计算机上的策略禁止用户安装,win10电脑安装摄像头驱动时提示策略禁止安装此设备的解决教程...
  5. 永不消逝的电波-wirteup
  6. Android studio添加依赖是什么意思以及添加依赖的方法
  7. java2048移动算法_2048游戏通关算法
  8. 网页中使用iconfont图标
  9. 春运抢火车票攻略汇总(持续更新中)
  10. Discuz!风格模版初级不完全修改教程