标题:
STM8S003F3关于IIC的STVD例子
[打印本页]
作者:
youxi297
时间:
2018-3-3 18:35
标题:
STM8S003F3关于IIC的STVD例子
STM8S003的IIC总是令人头大。现在附上一个STVD的例子。验证可以通过的
对于stm8,用库函数操作,上手容易,但是有好也有坏。这次手头上用到的是8S003这个芯片,如果上库函数,8M的内存很快就会被消耗殆尽,所以只能上寄存器操作,其实自己本人是比较喜欢直接操作寄存器的,对于stm8来说,寄存器也不是特别的多,一个一个来配置也不是特别麻烦,对于底层,也能有一个较好的了解,而除了前边所说的内存优势,执行效率也是有所差别。 stm8的iic,网上可谓是骂声一片啊,哈哈,这次调试之后发现确实是不够优秀,操作繁琐,而最重要的一点便是通讯速度的控制,通过对时钟寄存器的操作,来选择通讯速度,可是却和通过手册公式所计算出来的有很大差别,而最要命的一点是时钟上升沿时间,在寄存器中有一控制上升时间的寄存器,可是实际中通过示波器观察波形发现却是没有多大效果,或者说是没有效果(我的电路连接是iic引脚挂载一个24C02从设备,上拉电阻4K7)。
实际测试中,上升时间非常慢,对于100K的速度来说,这个上升时间太长了,再加上干扰或其他因素,极有可能大大降低通讯的可靠性。测试了一下,100K的速度,能正常驱动24C02(未长时间大数据量测试),而上400K的速度,通讯失败是常有的事。而手册中却是说着支持100K和400K的速度,且还有寄存器位专门来设置400K速度下的配置,正常来说是应该能上400K的速度才对。不知是否是我理解有误,配置的不好...!
谁弄过这个iic的,交流一下...!
上传我的工程文件,STVD,程序中各种while()的等待均没有设置超时退出。
程序是通过运行后在仿真窗口中观察变量来确认对24C02的读写。
单片机源程序如下:
/*
STM8硬件IIC,不用库的例子。
有空想试试STM8的硬件IIC读写24C02,结果不像软件模拟那么简单。。
为了一步一步验证读写程序,先用编程器把数据写到EEPROM内。然后就调试读的程序。。。
漫漫长的一天。。。终于成功。
*/
//记得配置选项字。
//SDA,SCL要上拉4.7K-10K的电阻。。
//相应端口要配置成默认的浮动输入。。。一定要。。
void IIC_Init(void)
{
//I2C_FREQR和I2C_CCRL,CCRH ,I2C_TRISER要对应fMASTER频率计算。。但测试的效果来看好像又没什么影响。
I2C_FREQR |= 0x0c; //输入外设时钟频率为11.0592MHz
I2C_CR1 = 0x00; //禁止I2C外设
I2C_TRISER = 0x0c;
I2C_CCRL = 0x37;
I2C_CCRH = 0x00;
I2C_CR1 |= 0x01; //开启I2C外设
I2C_CR2 |= 0x04; //应答使能
I2C_OARL = 0xfe; //自身地址
I2C_OARH = 0x40;
}
//读写之间插入3.5ms以上的延时,24C02写的时候不能应答。
//写24c02,参数:地址,长度1-16,数据缓冲
void Write_24c02(unsigned char address,unsigned char number,unsigned char *data)
{
unsigned char temp,i;
I2C_CR2 &=~ 0x04; //不返回应答
while(I2C_SR3 & 0x02); //等待总线空闲
I2C_CR2 |= 0x01; //产生起始位
while(!(I2C_SR1 & 0x01)); //等待START发送完
I2C_DR = 0xa0; //发24c02器件地址
while(!(I2C_SR1 & 0x02)); //等特7位器件地址发送完
temp = I2C_SR1;
temp = I2C_SR3;
I2C_DR = address;
while(!(I2C_SR1 & 0x04));
for(i=0;i<number;i++)
{
I2C_DR = *(data+i);
while(!(I2C_SR1 & 0x04));
}
I2C_CR2 |= 0x02; //产生停止位
I2C_CR2 |= 0x04; //返回应答
}
//读24C02,参数:返回的字节缓冲,开始地址,要读的字节数。
void Read_24c02(unsigned char *pBuffer,unsigned char address,unsigned char Number)
{
unsigned char temp,r_data;
while(I2C_SR3 & 0x02); //等待总线空闲
I2C_CR2 |= 0x01; //产生起始位
while(!(I2C_SR1 & 0x01)); //等待START发送完
I2C_DR = 0xa0; //发24c02器件地址
while(!(I2C_SR1 & 0x02)); //等特7位器件地址发送完
temp = I2C_SR1;
temp = I2C_SR3;
I2C_DR = address;
while(!(I2C_SR1 & 0x84));
I2C_CR2 |= 0x01; //产生重复起始位
while(!(I2C_SR1 & 0x01)); //等待START发送完
I2C_DR = 0xa1; //读
while(!(I2C_SR1 & 0x02)); //等特7位器件地址发送完
temp = I2C_SR1;
temp = I2C_SR3;
while(Number) //要读几个字节
{
if(Number== 1)
{
I2C_CR2 &= ~0x04; //不返回应答
I2C_CR2 |= 0x02; //产生停止位
}
if(I2C_SR1 & 0x40)
{
temp = I2C_SR1;
*pBuffer = I2C_DR;
pBuffer++;
Number--;
}
}
I2C_CR2 |= 0x04;
I2C_CR2 &= ~0x08;
}
/////
IIC_Init();
Read_24c02(buffer,0x0f,5);
for(i=0;i<5;i++)
{
while(!(UART2_SR&0x80)); //检测发送寄存器为空
UART2_DR = buffer[i];
while(!(UART2_SR&0x40)); //发送完成*/
}
for(vti=0;vti<5000;vti++); //延时一段时间再读呀。。。注意!!
buffer[0]=0xaa;
buffer[1]=0xbb;
buffer[2]=0xcc;
buffer[3]=0xdd;
buffer[4]=0xee;
Write_24c02(0x00,5,buffer);
for(vti=0;vti<5000;vti++); //延时一段时间再读呀。。。注意!!
Read_24c02(buffer,0x00,5);
for(i=0;i<5;i++)
{
while(!(UART2_SR&0x80)); //检测发送寄存器为空
UART2_DR = buffer[i];
while(!(UART2_SR&0x40)); //发送完成*/
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DE:IAR
MCU:STM8S105C6
外设IC:PL1167(2.4GRF)
下面贡献一下两个关键函数
void Write2Byte(u8 RomAddress,u8 v1,u8 v2)
{
SS_ENABLE;
I2C_GenerateSTART(ENABLE);
while(!I2C_GetFlagStatus(I2C_FLAG_STARTDETECTION));
I2C_Send7bitAddress(DeviceAddress, I2C_DIRECTION_TX);
while(!I2C_GetFlagStatus(I2C_FLAG_ADDRESSSENTMATCHED));
I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);// must add
I2C_SendData(RomAddress);
while(!I2C_GetFlagStatus(I2C_FLAG_TXEMPTY));
I2C_SendData(v1);
while(!I2C_GetFlagStatus(I2C_FLAG_TXEMPTY));
I2C_SendData(v2);
while(!I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED));
I2C_GenerateSTOP(ENABLE);
SS_DISABLE;
}
u16 PL1167_Read2Byte(u8 RomAddress)
{
u8 dat1,dat2;
u16 dat;
dat1=0;
dat2=0;
dat=0;
SS_ENABLE;
I2C_GenerateSTART(ENABLE);
while(!I2C_GetFlagStatus(I2C_FLAG_STARTDETECTION));
I2C_Send7bitAddress(DeviceAddress, I2C_DIRECTION_TX);
while(!I2C_GetFlagStatus(I2C_FLAG_ADDRESSSENTMATCHED));
I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);// must add
I2C_SendData(RomAddress);
while(!I2C_GetFlagStatus(I2C_FLAG_TXEMPTY));
I2C_GenerateSTART(ENABLE);
while(!I2C_GetFlagStatus(I2C_FLAG_STARTDETECTION));
I2C_Send7bitAddress(DeviceAddress, I2C_DIRECTION_RX);
while(!I2C_GetFlagStatus(I2C_FLAG_ADDRESSSENTMATCHED));
I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);// must add
while(!I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY));
I2C_AcknowledgeConfig(I2C_ACK_CURR);
dat1=I2C_ReceiveData();
I2C_AcknowledgeConfig(I2C_ACK_NONE);
while(!I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY));
dat2=I2C_ReceiveData();
I2C_GenerateSTOP(ENABLE);
dat|=dat1;
dat<<=8;
dat|=dat2;
SS_DISABLE;
return dat;
}
复制代码
所有资料51hei提供下载:
103244822STM8S-IIC.rar
(51.92 KB, 下载次数: 94)
2018-3-3 18:35 上传
点击文件名下载附件
IIC例程 STVD
下载积分: 黑币 -5
作者:
ekun2006
时间:
2018-9-7 21:56
顶一下
作者:
netbeetle
时间:
2018-9-7 23:28
STVD还真是少用哦,一般都用IAR。
作者:
fly_apple
时间:
2018-12-5 11:13
代码收下,有空试试。谢谢楼主
作者:
batihai
时间:
2019-10-13 15:52
正是我想参考的代码,多谢!
作者:
ewewew
时间:
2020-3-13 10:49
正是我想参考的代码,多谢!
作者:
405935987
时间:
2020-3-20 17:07
过来学习一下
作者:
kk一家
时间:
2023-11-17 16:47
非常好,正是我想用的
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1