在一段时间里,我的高中只能看数码管的十几个引脚发愣,觉得点灯是一个非常大且重要的工程之一,到了大学,才后知后觉有一种特殊的芯片可以对引脚进行管理,仅需要两个单片机的IO口就可以进行管理这个庞大的LED组合
目录
理论上需要供电必须足够,要不就会造成部分能亮起来,一下设置太多的时候就直接全灭了
一、准备工作
在手册中我们去了解是如何做到的通信
读图:
一、我们可以将CLK线作为“眼睛”,当CLK睁开的时候,SDA的信号才当真
二、信号的组成部分
①Start
②data1
③wait ask
④data2
⑤wait ask
⑥Stop
至此我们已经完成了最基本的一次模拟I2C的基本时序
我们去查接下来的所有需要的东西
显然我们需要使用模式命令,以及下面组合成八级亮度,7/8段显示以及开启
//开始信号
void Start_I2C()
{
//先将全部拉高_前提是输出模式
SDA_OUT_MODE();
SDA_1();
CLK_1();//睁开眼
//拉高两个为start做准备
SDA_0();//其下降沿就是start信号
//因为信号建立的速度在ns级别,所以延时1ms就够了
SDA_0();
CLK_0();//为下个信号埋伏笔
}
void Stop_I2C()
{
SDA_OUT_MODE();
CLK_0();//初始状态闭上眼_免得误会
SDA_0();
CLK_1();//睁开眼
SDA_1();
CLK_0();//闭上眼,避免误会
SDA_0();
}
void I2C_SendByte(uint8_t data)
{
//使用for写将需要输出的数据拆开,对应位设置好后让clk睁开眼
SDA_OUT_MODE();
//复位
CLK_0();
SDA_0();
for (int i = 0; i < 8; ++i) {
//拆_无保留必要
if((data&128) == 128)
{
SDA_1();//拉高
}
else
{
SDA_0();
}
CLK_1();
CLK_0();
///完成一次写入
//数据更新左移
data<<=1;
}
}
void Wait_Ask()
{
uint8_t timeout =1;//用来计时,等待SDA被拉低
SDA_IN_MODE();
//判断是否变成了预计中sda被拉低了,然后再把clk抬高
//给一段时间
while(timeout <=10 && HAL_GPIO_ReadPin(SDA_GPIO_Port,SDA_Pin) != 0)
timeout++;
CLK_1();//抬高clk
//printf("we have not recall");
}
void set_tm(uint8_t add,uint8_t data)
{
//完成一次设
Start_I2C();
I2C_SendByte(add);//第一个显存104**
Wait_Ask();
I2C_SendByte(data);//128
Wait_Ask();
Stop_I2C();
}
void RCCdelay_us(uint32_t udelay)
{
__IO uint32_t Delay = udelay * 72 / 8;//(SystemCoreClock / 8U / 1000000U)
//见stm32f1xx_hal_rcc.c -- static void RCC_Delay(uint32_t mdelay)
do
{
__NOP();
}
while (Delay --);
}
static void SDA_OUT_MODE()
{
//重新设置为输出
GPIO_InitTypeDef SDA;
SDA.Pin = SDA_Pin;
SDA.Mode = GPIO_MODE_OUTPUT_PP;
SDA.Pull = GPIO_PULLUP;
SDA.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &SDA);
}
static void SDA_IN_MODE()
{
//重新设置为输入
GPIO_InitTypeDef SDA;
SDA.Pin = SDA_Pin;
SDA.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOB, &SDA);
}
使用宏简便输入
理论上需要供电必须足够,要不就会造成部分能亮起来,一下设置太多的时候就直接全灭了