/*
用于支持SGM5348-12的SPI驱动程序定义
使用模拟SPI完成接口驱动,具体内容参见SGM5348-12数据手册
编写:宋连猛 2022.10.26
说明:1)芯片拥有4类指令,具体见代码:数据寄存器(0b0000~0b0111,数据12位),控制模式(0b1000,0b1001,数据全0),特殊指令(0b1010,0b1011,0b1100,数据8位和12位),断电模式(0b1101,0b1110,0b1111,数据8位);
2)供电电压2.8V~5.5V,参考电压:0.5~VCC,最高可到40Mhz数据频率;通常情况下,至少1uF+0.1uF过滤电源,使用TSSOP-16封装焊接方便,见数据手册;
3)数据使用SPI模式1(下降沿有效),注意最后1位的处理,时钟下降沿后,应同步信号调高电平,时钟等待后调高电平,见下面函数过程描述;
4)注意下面函数调用过程,方便理解;特别注意WRM和WTM的模式的使用环境:WRM->先写好值,再统一更新,WTM->写入即更新;注意CH1写模式的使用环境:其他先在WRM模式下写好非CH1数据,然后再调用CH1写模式统一更新;
5)sgm5348在上电后处于断电模式,此时要设置有效值,更新后输出电压,当人为进入断电模式后,使用更新指令可以恢复数据输出,数据保持在最后设置的值。
6)数据发送时高先低后,16位数据;
*/
#include "sgm5348_12_spi_driver.h"
//定义数据
uint16_t portectData[8]={0,0,0,0,0,0,0,0};//数据保存
//定义内部函数
//us延时函数
static void Delay_us(uint32_t time)
{
uint8_t i=0;
while(time--)
{
i=72/4; //自己定义,原值10
while(i--) ;
}
}
//ns延时函数
static void Delay_ns(uint32_t time)
{
uint8_t i=0;
while(time--)
{
i=3; //自己定义
while(i--) ;
}
}
//数据传送函数
static void spiPortectTransmiter(uint16_t value){
uint16_t tmp=value;
uint8_t i=16;
//1.时钟高,偏选高
sgm5348_12Portect_sclkHIGH;
sgm5348_12Portect_csHIGH;
//2.偏选低
sgm5348_12Portect_csLOW;
while(i!=0){
//3.数据给定
if(tmp&0x8000){//高
sgm5348_12Portect_dinkHIGH;
}else{//低
sgm5348_12Portect_dinkLOW;
}
//4.延时处理
Delay_ns(1);
//5.时钟低
sgm5348_12Portect_sclkLOW;
if(i!=1){//正常传输
//6.延时处理
Delay_ns(1);
//7.时钟高
sgm5348_12Portect_sclkHIGH;
}else{
//8.片选高
sgm5348_12Portect_csHIGH;
//6.延时处理
Delay_ns(1);
//7.时钟高
sgm5348_12Portect_sclkHIGH;
}
//8.数据位移,控制变量减1
tmp<<=1;
i--;
}
//8.数据低
sgm5348_12Portect_dinkLOW;
}
//写通道数据
static void writeChannelValue(uint8_t channel,uint16_t value){
uint16_t data=0;
data|=((channel&0x07)<<12);//地址位0b0xxxdddddddddddd
data|=(value&0xfff);//数据位0b0xxxdddddddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//写寄存器模式(不更新输出)
static void writeRegisterMode(void){
uint16_t data=0;
data|=(0x08<<12);//地址位0b1000000000000000
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//写通过模式(更新数据)
static void writeThroughMode(void){
uint16_t data=0;
data|=(0x09<<12);//地址位0b1001000000000000
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//更新选择模式
static void updateSelectMode(uint8_t value){
uint16_t data=0;
data|=(0x0A<<12);//地址位0b10100000dddddddd
data|=value;//地址位0b10100000dddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//CH1写模式命令(并更新全部通道)
static void writeCH1Mode(uint16_t value){
uint16_t data=0;
data|=(0x0B<<12);//地址位0b1011dddddddddddd
data|=(value&0xfff);//地址位0b1011dddddddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//广播模式命令(通输出电平)
static void broadcastMode(uint16_t value){
uint16_t data=0;
data|=(0x0C<<12);//地址位0b1100dddddddddddd
data|=(value&0xfff);//地址位0b1100dddddddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//断电高阻(HI-Z)输出命令
static void PowerDown_HI_Z(uint8_t value){
uint16_t data=0;
data|=(0x0D<<12);//地址位0b11010000dddddddd
data|=(uint16_t)(value&0xff);//地址位0b11010000dddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//断电2.5k电阻命令
static void PowerDown_2_5k(uint8_t value){
uint16_t data=0;
data|=(0x0E<<12);//地址位0b11100000dddddddd
data|=(uint16_t)(value&0xff);//地址位0b11100000dddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//断电100k电阻命令
static void PowerDown_100k(uint8_t value){
uint16_t data=0;
data|=(0x0F<<12);//地址位0b11110000dddddddd
data|=(uint16_t)(value&0xff);//地址位0b11110000dddddddd
spiPortectTransmiter(data);//自定义发送函数
Delay_us(1);//延时1us
}
//定义外部函数
//初始化通道数据:保护部分
void sgm5348_12_initPortectData(uint16_t* data,uint8_t length){
uint8_t i;
//1.进入WRM模式
writeRegisterMode();
//2.写入非CH1数据
if((length>1)&&(length<=8)){
for(i=1;i<length;i++){//遍历数据位置,从通道2开始处理
writeChannelValue(i,data[i]);
}
}
//3.写入1011命令带CH1数据
writeCH1Mode(data[0]);
}
//更新一个通道的数据:保护部分
void sgm5348_12_setPortectData(uint8_t channel,uint16_t data){
//1.进入WRM模式(用3.),或WTM模式(不用3.)
writeRegisterMode();
//writeThroughMode();
//2.写入CHn数据
writeChannelValue(channel,data);
//3.使用1010更新通道数据,后8个位
updateSelectMode(0xff);//操作有效
}
//开机:恢复电压输出
void sgm5348_12_PortectStart(void){
updateSelectMode(0xff);//更新有效
}
//关机:无输出电压
void sgm5348_12_PortectStop(void){
//PowerDown_HI_Z(0xff);//每路0.8V左右的悬空电压
//PowerDown_2_5k(0xff);//每路0V左右
PowerDown_100k(0xff);//每路0V左右
}
//广播控制:数据一致
void sgm5348_12_PortectBroadcast(uint16_t value){
broadcastMode(value);
}