STM8S TM1650芯片控制程序
以下为.h文件:
#ifndef __TM1650_I2C_H
#define __TM1650_I2C_H
#include "stm8s.h"
#include "stm8s_gpio.h"
#include "tim1.h"
#include "usart2.h"
#include <iostm8s103f3.h>
#include <intrinsics.h>
/**********************************
TM1650芯片控制20路灯函数
PB7为SCL口
PB6为SDA口
**********************************/
#define SCL_TM1650 PC_ODR_ODR7
#define SDA_TM1650 PC_ODR_ODR6
#define SDAM_TM1650 PC_IDR_IDR6
#define SET_SCL_OUT_TM1650() {PC_DDR_DDR7=1; PC_CR1_C17 = 1; PC_CR2_C27 = 0;}
#define SET_SDA_OUT_TM1650() {PC_DDR_DDR6=1; PC_CR1_C16 = 1; PC_CR2_C26 = 0;}
#define SET_SDA_IN_TM1650() {PC_DDR_DDR6=0; PC_CR1_C16 = 0; PC_CR2_C26 = 0;}
void IIC_Init_TM1650(void);
void TDelay_us(u8 z);
void I2C_Start_TM1650(void);
void I2C_Stop_TM1650(void);
void IIC_Ack_TM1650(void);
void IIC_NAck_TM1650(void);
uint8_t IIC_Wait_Ack_TM1650(void);
void IIC_WrByte_TM1650(uint8_t txd);
//u8 Scan_Key(void);
void TM1650_Set(u8 add,u8 dat);
void Init_Tm1650(void);
#endif
以下为.c文件:
#include "TM1650_I2C.h"
//--------------------------------------------------------------
// Prototype : void IIC_Init_TM1650(void)
// Calls :
// Description :
//--------------------------------------------------------------
void IIC_Init_TM1650(void)
{
SET_SCL_OUT_TM1650();
SET_SDA_OUT_TM1650();
SCL_TM1650 = 1;
SDA_TM1650 = 1;
}
//--------------------------------------------------------------
// Prototype : void Delay_us(void)
// Description : 大约延时 z us
//--------------------------------------------------------------
void TDelay_us(u8 z)
{
//u8 i; //fcpu 8MHz 时
//for (i=50; i>0; i--);
while(z--)
{
nop();nop();nop();nop();
}
}
//--------------------------------------------------------------
// Prototype : void I2C_Start(void)
// Calls : Delay_5us()
// Description : Start Singnal
//--------------------------------------------------------------
void I2C_Start_TM1650(void)
{
// SDA 1->0 while SCL High
//SCL高电平期间,SDA出现一个下降沿表示起始信号
SET_SDA_OUT_TM1650();
SDA_TM1650 = 1; //数据线先保持为高,起始信号要该口的下降沿
TDelay_us(4);
SCL_TM1650 = 1; //时钟线保持为高
TDelay_us(40); //有一个大概5us的延时具体以器件而定
SDA_TM1650 = 0; //数据线拉低出现下降沿
TDelay_us(4); //延时 一小会,保证可靠的下降沿
SCL_TM1650 = 0; //拉低时钟线,保证接下来数据线允许改变
}
//--------------------------------------------------------------
// Prototype : void I2C_Stop(void)
// Calls : Delay_5us()
// Description : Stop Singnal
//--------------------------------------------------------------
void I2C_Stop_TM1650(void)
{
// SDA 0->1 while SCL High
//SCL高电平期间,SDA产生一个上升沿 表示停止
SET_SDA_OUT_TM1650();
SCL_TM1650 = 0;
TDelay_us(2);
SDA_TM1650 = 0; //保证数据线为低电平
TDelay_us(40);
SCL_TM1650 = 1; //先保证时钟线为高电平
TDelay_us(10); //延时 以得到一个可靠的电平信号
SDA_TM1650 = 1; //数据线出现上升沿
TDelay_us(40); //延时 保证一个可靠的高电平
}
//应答函数
void IIC_Ack_TM1650(void)
{
//数据线一直保持为低电平,时钟线出现上升沿即为应答
SET_SDA_OUT_TM1650();
TDelay_us(10);
SDA_TM1650 = 0;
TDelay_us(10);
SCL_TM1650 = 0;
TDelay_us(40);
SCL_TM1650 = 1;
TDelay_us(40);
//应答完成后 将时钟线拉低 允许数据修改
SCL_TM1650 = 0;
}
//非应答
void IIC_NAck_TM1650(void)
{
//非应答即相反 与应答区别即为数据线保持高电平即可
SET_SDA_OUT_TM1650();
TDelay_us(10);
SDA_TM1650 = 1;
TDelay_us(10);
SCL_TM1650 = 0;
TDelay_us(40);
SCL_TM1650 = 1;
TDelay_us(40);
//最后要将时钟线拉低 允许数据变化
SCL_TM1650 = 0;
}
//等待应答
uint8_t IIC_Wait_Ack_TM1650(void)//0为有应答,1为无应答
{
//应答等待计数
uint8_t ackTime = 0;
//先将数据线要设置成输入模式本程序未体现,有应答则会出现下降沿
SCL_TM1650 = 0;
SET_SDA_OUT_TM1650();
TDelay_us(10);
SDA_TM1650 = 1;//
TDelay_us(30);
SET_SDA_IN_TM1650();//切换为输入模式
//时钟线拉高
SCL_TM1650 = 1;
TDelay_us(30);
//等待数据线拉低应答
while(SDAM_TM1650){
//如果在该时间内仍未拉低
ackTime ++;
if(ackTime > 250)
{
//认为非应答 停止信号
I2C_Stop_TM1650();
return 1;
}
}
SCL_TM1650 = 0;
return 0 ;
}
void IIC_WrByte_TM1650(uint8_t txd)
{
//定义一个计数变量
uint8_t i;
SET_SDA_OUT_TM1650();
//将时钟线拉低允许数据改变
// SCL = 0;
//按位发送数据
for(i = 0;i < 8; i ++)
{
TDelay_us(2);
if((txd&0x80)>>7) //0x80 1000 0000
SDA_TM1650=1;
else
SDA_TM1650=0;
txd<<=1;
TDelay_us(20);
SCL_TM1650=1;
TDelay_us(20);
SCL_TM1650=0;
TDelay_us(20);
}
}
/***************************
u8 Scan_Key(void) //按键扫描
{
u8 i;
u8 rekey;
I2C_Start_TM1650();
IIC_WrByte_TM1650(0x49);//读按键命令
IIC_Ack_TM1650();
//DIO_H;
SET_SDA_IN_TM1650();//切换为输入模式
for(i=0;i<8;i++)
{
SCL_TM1650=1;
rekey = rekey<<1;
if(SDAM_TM1650)
{
rekey++;
}
TDelay_us(5);
SCL_TM1650=0;
}
IIC_Ack_TM1650();
I2C_Stop_TM1650();
return(rekey);
}
****************************/
void TM1650_Set(u8 add,u8 dat) //数码管显示
{
//写显存必须从高地址开始写
I2C_Start_TM1650();
IIC_WrByte_TM1650(add); //第一个显存地址
IIC_Ack_TM1650();
IIC_WrByte_TM1650(dat);
IIC_Ack_TM1650();
I2C_Stop_TM1650();
}
void Init_Tm1650(void)
{
IIC_Init_TM1650();
delay_ms(50); //需要延时一小段时间,否则开显示会无响应
TM1650_Set(0x48,0x31);//初始化为5级灰度,开显示
}
注意:TM1650芯片启动可能需要一点时间,故发送开显示前应延时一小段时间,否则会收不到。