目录
根据HT1622数据手册中的时序图可知:
1)从N1处可知,当CS处于低电平时,WR才有效。
2)从N2处可知,当CS处于低电平,且当WR脚处于上升沿时,DATA才有效。
3)从N3处可知,向HT1622传送指令的通讯协议格式为:3位命令标识+9位指令。
4)从N4处可知,向HT1622传送数据的通讯协议格式为:3位命令标识+6位地址+4位数据。
5)从N5处可知,向HT1622连续传送多组数据,后续数据会自动更新写入到下一个地址。
6)从N3/N4/N5处可知,向HT1622写入数据时,指令和地址是从高位写入,数据是从低位写入。
由HT1622 RAM映射表可知,SEGx 和 其首地址Addr 的关系(Addr = SEGx * 2),是连续映射的。所以在写入数据时,可以使用SEGx代替地址,一次写入8位数据(控制SEGx下的8个COM),能更简洁直观地对断码屏进行操作。注意,有的屏幕供应商提供的DataSheet,SEG是从1开始计数,而不是0。(我手中断码屏DataSheet(如下图)的就是从1开始计数)
写驱动函数:
*注:我的工程中移植了RT_Thread,故延时函数使用的是 rt_thread_delay();
#define DISPLAY 1 // 显示
#define HIDE 0 // 隐藏
// 定义数据IO口
#define ScreenBLED_ON Screen_BLED_GPIO_Port->BSRR = Screen_BLED_Pin // 开启屏幕背光
#define ScreenBLED_OFF Screen_BLED_GPIO_Port->BRR = Screen_BLED_Pin // 关闭屏幕背光
#define ScreenCS_H Screen_CS_GPIO_Port->BSRR = Screen_CS_Pin // 将CS拉高
#define ScreenCS_L Screen_CS_GPIO_Port->BRR = Screen_CS_Pin // 将CS拉低
#define ScreenWR_H Screen_WR_GPIO_Port->BSRR = Screen_WR_Pin // 将WR拉高
#define ScreenWR_L Screen_WR_GPIO_Port->BRR = Screen_WR_Pin // 将WR拉低
#define ScreenDATA_H Screen_DATA_GPIO_Port->BSRR = Screen_DATA_Pin // 将DATA拉高
#define ScreenDATA_L Screen_DATA_GPIO_Port->BRR = Screen_DATA_Pin // 将DATA拉低
// 定义指令代码
#define SYSDIS 0x00 // 0b 0000 0000 关闭系统振荡器和LCD偏压发生器
#define SYSEN 0x01 // 0b 0000 0001 打开系统振荡器
#define LCDOFF 0x02 // 0b 0000 0010 关闭LCD偏压
#define LCDON 0x03 // 0b 0000 0011 打开LCD偏压
#define WDTDIS 0x05 // 0b 0000 0101 禁止看门狗
#define RC32K 0x18 // 0b 0001 1000 内部时钟
#define TONEOFF 0x08 // 0b 0000 1000 关闭声音输出
// "8"形状数码屏数字定义
uint8_t NumData[10] = {0xEE, 0x24, 0xD6, 0xB6, 0x3C, 0xBA, 0xFA, 0x26, 0xFE, 0xBE}; // 0~9
// 定义显示数字区域的SEGx,从低位到高位
uint8_t SEG_ShowNum[4] = {6, 5, 4, 3};
//===========================================================================
// 函数名: WrBit_H
// 功能 : 将数据data从高位开始(高-->低),写入cnt位
// 参数 : data:写入的数据;cnt:写入位数
// 返回值: none
//===========================================================================
void WrBit_H(uint8_t data, uint8_t cnt)
{
uint8_t i;
for (i = 0; i < cnt; i++)
{
ScreenWR_L;
rt_thread_delay(1);
if (data & 0x80)
ScreenDATA_H;
else
ScreenDATA_L;
rt_thread_delay(1);
ScreenWR_H;
rt_thread_delay(1);
data <<= 1;
}
}
//===========================================================================
// 函数名: WrBit_L
// 功能 : 将数据data从低位开始(高<--低),写入cnt位
// 参数 : data:写入的数据;cnt:写入位数
// 返回值: none
//===========================================================================
void WrBit_L(uint8_t data, uint8_t cnt)
{
uint8_t i;
for (i = 0; i < cnt; i++)
{
ScreenWR_L;
rt_thread_delay(1);
if (data & 0x01)
ScreenDATA_H;
else
ScreenDATA_L;
rt_thread_delay(1);
ScreenWR_H;
rt_thread_delay(1);
data >>= 1;
}
}
//===========================================================================
// 函数名: HT1622WrCmd
// 功能 : 向HT1622写入指令
// 参数 : Cmd:指令代码
// 返回值: none
//===========================================================================
void HT1622WrCmd(uint8_t Cmd)
{
ScreenCS_L;
rt_thread_delay(1);
WrBit_H(0x80, 3); // 写入命令标志
WrBit_H(Cmd, 9); // 写入命令数据
ScreenCS_H;
rt_thread_delay(1);
}
//===========================================================================
// 函数名: HT1622WrData
// 功能 : 向HT1622的SEGx写入8位数据(直接控制SEGx下的所有内容)
// 参数 : SEGx:数据映射表中的SEGx列;Data:要写入的控制数据
// 返回值: none
//===========================================================================
void HT1622WrData(uint8_t SEGx, uint16_t Data)
{
uint8_t Addr;
Addr = (SEGx - 1) * 2;
ScreenCS_L;
rt_thread_delay(1);
WrBit_H(0xA0, 3); // 写入数据标志
WrBit_H(Addr << 2, 6); // 写入6位地址
WrBit_L(Data, 8); // 写入8位数据
ScreenCS_H;
rt_thread_delay(1);
}
//===========================================================================
// 函数名: FullScreenContent
// 功能 : 控制全屏的内容为 显示/隐藏
// 参数 : state:显示状态(DISPLAY/HIDE)
// 返回值: none
//===========================================================================
void FullScreenContent(uint8_t state)
{
ScreenCS_L;
rt_thread_delay(1);
WrBit_H(0xA0, 3); // 写入数据标志
WrBit_H(0x00, 6); // 写入6位地址
// 对所有地址写入数据 1/0 —— DISPLAY/HIDE
for (uint16_t i = 0; i < 8 * 32; i++)
{
ScreenWR_L;
rt_thread_delay(1);
if (state)
ScreenDATA_H;
else
ScreenDATA_L;
rt_thread_delay(1);
ScreenWR_H;
rt_thread_delay(1);
}
ScreenCS_H;
rt_thread_delay(1);
}
//===========================================================================
// 函数名: DisplayNum
// 功能 : 在段码屏的数字显示区域SEG_ShowNum显示数字
// 参数 : Num:要显示的多位数
// 返回值: none
//===========================================================================
void DisplayNum(uint16_t Num)
{
for (uint8_t i = 0; i < sizeof(SEG_ShowNum); i++)
{
if ((Num == 0) && (i != 0))
HT1622WrData(SEG_ShowNum[i], 0x00);
else
HT1622WrData(SEG_ShowNum[i], NumData[Num % 10]);
Num /= 10;
}
}
//===========================================================================
// 函数名: Screen_Init
// 功能 : 屏幕初始化
// 参数 : none
// 返回值: none
//===========================================================================
void Screen_Init(void)
{
ScreenCS_H;
ScreenWR_H;
ScreenDATA_H;
ScreenBLED_ON;
rt_thread_mdelay(1000);
HT1622WrCmd(RC32K);
HT1622WrCmd(SYSEN);
HT1622WrCmd(LCDON);
FullScreenContent(HIDE);
// 测试例程:倒数计数显示
for (int16_t i = 110; i >= 0; i--)
{
rt_thread_delay(10);
DisplayNum(i);
}
}
测试例程:倒数计数显示效果
段码屏倒数显示效果
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
我使用的是最新版本的Chrome(32.0.1700.107)和Chrome驱动程序(V2.8)。但是当我在Ruby中使用以下代码运行示例测试时:require'selenium-webdriver'WAIT=Selenium::WebDriver::Wait.new(timeout:100)$driver=Selenium::WebDriver.for:chrome$driver.manage.window.maximize$driver.navigate.to'https://www.google.co.in'defapps_hoverele_hover=$driver.find_
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。多年来,我一直在使用多种语言进行编程,并且认为自己总体上相当擅长。但是,我从未编写过任何自动化测试:没有单元测试,没有TDD,没有BDD,什么都没有。我已经尝试开始为我的项目编写适当的测试套件。我可以看到在进行任何更改后能够自动测试项目中所有代码的理论值(value)。我可以看到像RSpec和Mocha这样的测试框架应该如何使设置和运行所述测试变得相当容易
如果我在功能规范中调用url_for,它会返回一个以http://www.example.com/开头的绝对URL.Capybara会很乐意尝试加载该站点上的页面,但这与我的应用程序无关。以下是重现该问题的最少步骤:从这个Gemfile开始:source'https://rubygems.org'gem"sqlite3"gem"jquery-rails"gem"draper"gem"rails",'4.1.0'gem"therubyracer"gem"uglifier"gem"rspec-rails"gem"capybara"gem"poltergeist"gem"launchy"运行
在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种方法,觉得有必要详细分析一下他是如何实现的进程隐藏的,总体来说作者的思路是最终寻找到MiProcessLoaderEntry的入口地址,该函数的作用是将驱动信息加入链表和移除链表,运用这个函数即可动态处理驱动的添加和移除问题。MiProcessLoaderEntry(pDriverObject->DriverSection,1)添加MiProcessLoaderEntry(pDriverObject->DriverSection,
我有一个适用于事件/监听器模型的应用程序。发布了几种不同类型的数据(事件),然后许多不同的事情可能需要也可能不需要对该数据(监听器)采取行动。监听器的发生没有特定的顺序,每个监听器将决定是否需要对事件采取行动。Rails应用程序有哪些工具可以完成此任务?我希望自己不必这样做(尽管我可以。这没什么大不了的。)编辑:观察者模式可能是更好的选择 最佳答案 查看EventMachine.它是一个非常流行的Ruby事件处理库。它看起来相当不错,而且很多其他库似乎都在利用它(Cramp)。这是一个很好的介绍:http://rubylearnin
一、概述在之前的一篇博文中,记录了AT24C01、AT24C02芯片的读写驱动,先将之前的相关文章include一下:1.IIC驱动:4位数码管显示模块TM1637芯片C语言驱动程序2.AT24C01/AT24C02读写:AT24C01/AT24C02系列EEPROM芯片单片机读写驱动程序本文记录分享AT24C04、AT24C08、AT24C16芯片的单片机C语言读写驱动程序。二、芯片对比介绍型号容量bit容量byte页数字节/页器件寻址位可寻址器件数WordAddress位数/字节数备注AT24C044k5123216A2A149/1WordAddress使用P0位AT24C088k1024
是的,我开始做这个测试了!但是我不知道该用什么=/Rspec+应该吗?Rspec+牛排?迷你测试?cucumber?capybara?可以吗?(cucumber与Shoulda混合)迷你应该吗?(Minitest与Shoulda混合)啊,这么多选择!我很困惑你们用什么,为什么? 最佳答案 如果您刚刚开始,您应该使用默认值并遵循theofficialguides.重要的是你要练习测试。您使用哪种测试库/框架并不重要——这是一种风格选择,在实际练习测试中是次要的——开始测试Rails应用程序的最简单方法是遵循“Golden官方指南布局的
我正在使用Cucumber+capybara进行一些网络自动化测试。我希望能够连接我自己的标签(类似于场景之前的@all_browsers)并让它针对我设置的网络驱动程序列表运行(celerity,firefox上的selenium,ie和chrome)。我不想在前面用4个不同的标签写4次不同的场景。我已经研究过尝试使用我通过以下方式注册的新驱动程序来执行此操作:Capybara.register_driver:all_browsersdo|app|#Whatwouldevenworkinhere?Idon'tthinkanythingwill.end然后跟进:Before('@all