📄 ht7289b-c.c
字号:
// ht7289b-c.c
// pic16f84a, 4.0MHz XTAL
// hi-tech picc compiler v9.50
#include <pic.h>
__CONFIG(XT & WDTEN & PWRTEN);
// spi interface define
#define CS RA2 // I/O数据
#define SDA RA1
#define SCK RA0
#define CS_C TRISA2 // I/O方向
#define SDA_C TRISA1
#define SCK_C TRISA0
// global variables
unsigned char timeCount;
unsigned char byteCount;
unsigned char spiBuffer[16];
struct
{
unsigned b0 : 1;
unsigned b1 : 1;
} flag;
#define KEY_ARQ flag.b0 // 重发标志
#define DAT_ARQ flag.b1
/*******************************************************/
/*****************SPI 收发程序**************************/
/*******************************************************/
// delay 500us
void Delay500us(void)
{
unsigned char i;
for (i = 165; i != 0; i--)
{
}
NOP(); // 该语句不能省,否则for{}语句会被编译器优化掉
}
// delay 50us
void Delay50us(void)
{
unsigned char i;
for (i = 15; i != 0; i--)
{
}
NOP(); // 该语句不能省
}
// delay 20us
void Delay20us(void)
{
unsigned char i;
for (i = 5; i != 0; i--)
{
}
NOP(); // 该语句不能省
}
// Get Data from SPI
unsigned char GetSPIByte(void)
{
unsigned char i, temp;
SDA_C = 1; // SDA as input
i = 8; // 8 bits
do
{
SCK = 0;
NOP(); // SCK拉低至少4us
NOP();
NOP();
NOP();
SCK = 1;
temp <<= 1;
if (SDA == 1)
{
temp |= 0x01;
}
NOP(); // SCK为高至少4us
} while (--i != 0);
return temp;
}
// Put Data to SPI
void PutSPI(unsigned char len)
{
unsigned char i, j, temp;
SCK = 1; // SCK输出高
SCK_C = 0;
CS = 0; // CS拉低
CS_C = 0;
SDA_C = 0; // SDA作为输出
Delay50us(); // 从CS拉低到SCK下降沿延时50us
i = 0;
do
{
temp = spiBuffer[i];
j = 8; // 8 bits
do
{
SCK = 0; // SCK拉低至少4us
SDA = 0;
if ((temp & 0x80) != 0)
{
SDA = 1;
}
temp <<= 1;
NOP();
SCK = 1; // SCK为高至少4us
NOP();
} while (--j != 0);
i++; // 下一字节
NOP(); // 字节之间时间间隔至少8us
} while (--len != 0);
SDA_C = 1; // 发送完毕SDA作为输入
}
// stop SPI
void StopSPI(void)
{
CS = 1;
}
// 主程序
void main(void)
{
// init I/O
CLRWDT();
INTCON = 0;
TMR0 = 6;
OPTION = 0x01; // TMR0 prescaler 1:4
PORTA = 0x05; // CS & SCK output high, SDA as input
TRISA = 0x0a;
timeCount = 206;
while (1)
{
while (!T0IF) ; // 等待1ms定时到
INTCON = 0;
TMR0 = 6;
OPTION = 0x01; // TMR0 prescaler 1:4
CLRWDT(); // 清WDT
if (++timeCount == 0) // 50ms
{
timeCount = 206;
KEY_ARQ = 0;
/***********************************************************/
/*******************50ms读取一次按键***********************/
/***********************************************************/
ReadKey:
spiBuffer[0] = 0xc0; // 0xc0--命令
spiBuffer[1] = 0x03; // 0x03--按键滤波参数,表示15ms按键有效
spiBuffer[2] = 0x0a; // 0x0a--命令字尾
PutSPI(3); // 3个字节
Delay20us();
spiBuffer[0] = GetSPIByte(); // 按键返回
spiBuffer[1] = GetSPIByte();
spiBuffer[2] = GetSPIByte();
StopSPI(); // 结束SPI通讯
if (spiBuffer[0] != 0xac) // 返回命令字错误
{
goto KeyError;
}
if (spiBuffer[2] != 0x0a) // 返回命令字尾错误
{
goto KeyError;
}
if ((spiBuffer[1] & 0x7f) >= 0x38) // 无按键
{
goto KeyEnd;
}
if (spiBuffer[1] >= 0x80) // 本演示程序不处理连击键
{
goto KeyEnd;
}
byteCount = 0;
switch (spiBuffer[1])
{
case 0x0:
// 显示复位
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0xaa;
spiBuffer[2] = 0x55;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x01:
// 直接显示: DIG0-DIG7对应显示A-DP段
spiBuffer[0] = 0xd6;
spiBuffer[1] = 0x80;
spiBuffer[2] = 0x80;
spiBuffer[3] = 0x40;
spiBuffer[4] = 0x20;
spiBuffer[5] = 0x10;
spiBuffer[6] = 0x08;
spiBuffer[7] = 0x04;
spiBuffer[8] = 0x02;
spiBuffer[9] = 0x01;
spiBuffer[10] = 0x0a;
byteCount = 11;
break;
case 0x02:
// 译码显示: DIG0-DIG7对应显示数字1-5,6(带小数点),7-8
spiBuffer[0] = 0xdc;
spiBuffer[1] = 0x80;
spiBuffer[2] = 0x01;
spiBuffer[3] = 0x02;
spiBuffer[4] = 0x03;
spiBuffer[5] = 0x04;
spiBuffer[6] = 0x05;
spiBuffer[7] = 0x86;
spiBuffer[8] = 0x07;
spiBuffer[9] = 0x08;
spiBuffer[10] = 0x0a;
byteCount = 11;
break;
case 0x03:
// 译码显示: DIG0-DIG7对应显示数字A-F, [blank], -
spiBuffer[0] = 0xdc;
spiBuffer[1] = 0x80;
spiBuffer[2] = 0x0a;
spiBuffer[3] = 0x0b;
spiBuffer[4] = 0x0c;
spiBuffer[5] = 0x0d;
spiBuffer[6] = 0x0e;
spiBuffer[7] = 0x0f;
spiBuffer[8] = 0x10;
spiBuffer[9] = 0x1e;
spiBuffer[10] = 0x0a;
byteCount = 11;
break;
case 0x08:
// 位闪烁: DIG5闪烁
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x10;
spiBuffer[2] = 0x04;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x09:
// 段闪烁: DIG5的DP段闪烁
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x1d;
spiBuffer[2] = 0x01;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x0a:
// 闪烁频率: 1Hz
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x20;
spiBuffer[2] = 0x01;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x0b:
// 闪烁频率: 5Hz
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x20;
spiBuffer[2] = 0x03;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x10:
// 亮度调节: 1/16(最暗)
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x30;
spiBuffer[2] = 0x01;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x11:
// 亮度调节: 1/4
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x30;
spiBuffer[2] = 0x04;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x12:
// 亮度调节: 1/2
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x30;
spiBuffer[2] = 0x08;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x13:
// 亮度调节: 全亮
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x30;
spiBuffer[2] = 0x00;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x18:
// 位隐显: DIG0隐显
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x00;
spiBuffer[2] = 0x80;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x19:
// 位显示: DIG0显示
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x70;
spiBuffer[2] = 0x80;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x1a:
// 段关闭: DIG1的G段关闭
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x09;
spiBuffer[2] = 0x02;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
case 0x1b:
// 段点亮: DIG1的G段电亮
spiBuffer[0] = 0xd0;
spiBuffer[1] = 0x79;
spiBuffer[2] = 0x02;
spiBuffer[3] = 0x0a;
byteCount = 4;
break;
default:
break;
}
if (byteCount == 0) // 未知按键,不处理
{
goto KeyEnd;
}
Delay50us(); // 连续两次数据收发至少延时50us
DAT_ARQ = 0;
for (; ;)
{
PutSPI(byteCount);
Delay20us();
if (GetSPIByte() == 0xaa) // 数据发送成功
{
StopSPI();
goto KeyEnd;
}
StopSPI();
if (DAT_ARQ == 1) // 只重发一次
{
goto KeyEnd;
}
Delay500us();
DAT_ARQ = 1; // 发送失败则延时500us后重发
}
KeyError:
if (KEY_ARQ != 1) // 之前未重发
{
Delay500us();
KEY_ARQ = 1;
goto ReadKey;
}
KeyEnd:;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -