发新帖本帖赏金 5.50元(功能说明)我要提问
返回列表
打印
[开源硬件]

DIY多功能12864液晶显示电子台历-设计篇

[复制链接]
楼主: henangongda123
手机看帖
扫描二维码
随时随地手机跟帖
41
henangongda123|  楼主 | 2018-5-29 16:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览

使用特权

评论回复
42
henangongda123|  楼主 | 2018-5-29 16:50 | 只看该作者
这两天身体不舒服,工作也忙,今天开始调试DS3231时钟芯片。

使用特权

评论回复
43
21ic小喇叭| | 2018-6-1 09:02 | 只看该作者
强大,期待继续更贴~

使用特权

评论回复
44
henangongda123|  楼主 | 2018-6-1 09:18 | 只看该作者
21ic小喇叭 发表于 2018-6-1 09:02
强大,期待继续更贴~

卡在STM8S 硬件I2C上了,呵呵 今天把压箱底的虚拟示波器拿出来了,准备看看咋回事。

使用特权

评论回复
45
henangongda123|  楼主 | 2018-6-1 09:26 | 只看该作者
这两天在调试STM8S 硬件I2C通信,不知道是DS3231的问题还是STM8S的问题,反正现在卡住了,哈哈,今早专门翻箱底,把2011年买的虚拟示波器拿出来了,擦干净试了下,嘿嘿,还能用!没示波器调试MCU,简直是瞎啊

虚拟示波器.jpg (438.9 KB )

虚拟示波器.jpg

虚拟示波器界面.jpg (251.66 KB )

虚拟示波器界面.jpg

使用特权

评论回复
46
henangongda123|  楼主 | 2018-6-1 23:45 | 只看该作者
DS3231终于调试通了,哈哈!主要问题在于没搞清楚时序,附上源代码和参考资料:
/********* 硬件I2C操作 **********/
//初始化函数
/***********************************************************
函数名: I2C_Init()
功  能: STM8S207 MCU硬件I2C初始化
        (注: 主模式,两线连接,7位地址模式,10Kbps通信速率)
参  数: 无
返回值: 无
***********************************************************/
void I2C_Init(void)
{
  I2C_FREQR = 0x02;           //配置I2C外设时钟2MHz
        I2C_CCRH = 0x00;            //配置I2C为标准模式
        I2C_CCRL = 0x64;            //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
        I2C_TRISER = 0x03;          //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
        CLK_PCKENR1 |= 0x01;        //使能I2C时钟
        I2C_CR1 |= 0x01;            //启动I2C硬件模块
}

//DS3231读取年、月、日、时、分、秒、星期等数据
/***********************************************************
函数名: DS3231_Read()
功  能: STM8S207 MCU通过硬件I2C读取DS3231内年月日时分秒等数据
参  数: data_buff --- 从DS3231读取的多字节数据指针
                          data_len  --- 从DS3231读取的多字节数据长度(7个)
返回值: 无
***********************************************************/
void DS3231_Read(uchar *data_buff,uchar data_len)
{         
        uchar temp,data_recv;       //定义一下,读取MCU状态寄存器、数据寄存器用
        while(I2C_SR3&0x02);        //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        while(!(I2C_SR1&0x01));     //I2C_SR1状态寄存器SB位=1表示发送成功
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD0;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=0表示写操作)
        while(!(I2C_SR1&0x02));     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_DR = 0x00;              //发送DS3231寄存器地址(WORD ADDRESS,从00H到12H)
        while(!(I2C_SR1&0x84));     //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1,表示发送时数据寄存器为空且数据字节发送完毕)
        I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
        while(!(I2C_SR1&0x01));     //I2C_SR1状态寄存器SB位=1表示发送成功
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD1;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=1表示读操作)
        while(!(I2C_SR1&0x02));     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        while(data_len)             //循环读取数据
        {
                if(data_len == 1)         //如果是接收最后一位数据
                {
                        I2C_CR2 &= 0xFB;        //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
                        I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位//必须清除先I2C_SR1状态寄存器BTF位)
                }
                if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
                {
                        *data_buff = I2C_DR;    //读取数据寄存器内数值,同时清除BTF位
                        data_buff++;            //准备接收下一字节数据
                        data_len--;
                }
        }
        I2C_CR2        |= 0x04;            //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
}

DS3231调试-1.jpg (440.31 KB )

DS3231调试-1.jpg

DS3231调试-2.jpg (462.07 KB )

DS3231调试-2.jpg

DS3231-秒钟.jpg (393.36 KB )

DS3231-秒钟.jpg

stm8调试硬件I2C心得.pdf

169.74 KB

使用特权

评论回复
评论
blust5 2018-7-4 08:20 回复TA
I2C的时序确实是关键问题,还有ACK响应问题,有的外设没有接到ACK响应不会发送下一字节数据的。。。 
47
henangongda123|  楼主 | 2018-6-2 00:57 | 只看该作者
好奇怪,高兴的太早了,断电后居然发现程序有问题,用示波器看了下,SCL时钟线居然一直是低电平,导致程序卡死在了检测总线是否忙碌那地方,貌似是单片机的问题,因为网上有人遇到类似问题:http://www.eemaker.com/stm8s-i2c-busy.html
貌似和I2C初始化有关系,明天好好排查一下这个问题!

使用特权

评论回复
48
henangongda123|  楼主 | 2018-6-2 09:08 | 只看该作者
不止一个人遇到我这样的问题,哈哈,今天得好好看一下什么原因了!
https://bbs.21ic.com/forum.php?mod=viewthread&tid=1593906
https://bbs.21ic.com/icview-701020-1-1.html
http://www.stmcu.org/module/forum/thread-602129-1-1.html

使用特权

评论回复
49
henangongda123|  楼主 | 2018-6-2 09:16 | 只看该作者
哈哈 似乎找到问题原因!确实是单片机复位后会出现这个现象。

I2C互锁问题.png (72.71 KB )

I2C互锁问题.png

使用特权

评论回复
50
henangongda123|  楼主 | 2018-6-2 23:01 | 只看该作者
今天根据这篇**的分析建议,DS3231读取数据程序增加了I2C通信防锁死操作(SCL发送9个脉冲信号),虽然提高了不少读取数据成功率(单片机掉电后再通电或者I2C通信受干扰会出现这种锁死情况),而且出现锁死后复位单片机一次就可以解决问题,但还不够理想(不能老是按复位键吧,呵呵)

DS3231增加I2C通信防锁死程序.jpg (476.33 KB )

DS3231增加I2C通信防锁死程序.jpg

I2C通信防锁死解决方案.png (87.95 KB )

I2C通信防锁死解决方案.png

使用特权

评论回复
评论
blust5 2018-7-4 08:40 回复TA
@henangongda123 :主要是坑多,不同MCU坑可能还会不一样,没有模拟I2C的通用性强 
henangongda123 2018-7-4 08:31 回复TA
@blust5 :经过我的调试,现在STM8S硬件I2C用的也很稳定、方便 
blust5 2018-7-4 08:22 回复TA
I2C一直用的模拟。。。 
51
henangongda123|  楼主 | 2018-6-3 21:23 | 只看该作者
现在I2C锁死问题已经解决了,但新的问题是STM8S硬件清除BUSY位有点坑爹,这个标志位无法用软件操作清除,只能由外部信号变化反馈给单片机I2C硬件才能清除,一旦I2C通信不稳定,误触发这个标志位就很麻烦,目前是必须得复位单片机才能过了这个坎。。。正在想办法解决这个问题。另外上传、分享增加I2C防锁死及优化的程序源代码:
//DS3231读取年、月、日、时、分、秒、星期等数据
/***********************************************************
函数名: DS3231_Read()
功  能: STM8S207 MCU通过硬件I2C通信读取DS3231内年月日时分秒等数据
参  数: data_buff --- 从DS3231读取的多字节数据指针
                          data_len  --- 从DS3231读取的多字节数据长度(7个)
返回值: 无
***********************************************************/
void DS3231_Read(uchar *data_buff,uchar data_len)
{         
        uchar temp;                 //定义一下,读取MCU状态寄存器用
        uchar i;                    //定义一下,供循环使用
        //以下程序为I2C通信防锁死操作,非常重要!
        if((PE_IDR&0x04) == 0x00)   //检测总线是否忙碌中(忙碌则SCL=1,SDA=0)
        {
                I2C_CR1 &= 0xFE;          //禁用I2C硬件模块,准备直接操作端口
                PE_DDR |= 0x02;           //设置SCL端口为输出
                PE_CR1 |= 0x02;           //上拉输出
                for(i=0;i<9;i++)          //SCL端口发出9个时钟脉冲,让从设备DS3231释放总线(恢复SDA=1)
                {
                        PE_ODR &= 0xFD;         //SCL=0;
                        delay_us(50);           //延时(I2C通信频率10KHz)
                  PE_ODR |= 0x02;         //SCL=1
                  delay_us(50);           //延时(I2C通信频率10KHz)
                }
                while(!(PE_IDR&0x04));    //等待数据线SDA=1
                PE_DDR &= 0xFD;           //SCL端口恢复输入方式
                PE_CR1 &= 0xFD;           //浮空输入
                PE_ODR &= 0xFD;           //清零输出寄存器
                I2C_CR1 |= 0x01;          //重新启动I2C硬件模块(接管SCL、SDA端口)
        }
        //以上程序为I2C通信防锁死操作,非常重要!
        if((I2C_SR3&0x02) == 0x02)  //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
        {
               
        }
        while(I2C_SR3&0x02);        //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        while(!(I2C_SR1&0x01));     //I2C_SR1状态寄存器SB位=1表示发送成功
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD0;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=0表示写操作)
        while(!(I2C_SR1&0x02));     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_DR = 0x00;              //发送DS3231寄存器地址(WORD ADDRESS,从00H到12H)
        while(!(I2C_SR1&0x84));     //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
        while(!(I2C_SR1&0x01));     //I2C_SR1状态寄存器SB位=1表示发送成功
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD1;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=1表示读操作)
        while(!(I2C_SR1&0x02));     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_CR2        |= 0x04;            //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
        while(data_len)             //循环读取数据
        {
                if(data_len == 1)         //如果是接收最后一位数据(特殊处理)
                {
                        I2C_CR2 &= 0xFB;        //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
                        I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
                }
                if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
                {
                        *data_buff = I2C_DR;    //读取数据寄存器内数值,同时清除BTF位
                        data_buff++;            //准备接收下一字节数据
                        data_len--;
                }
        }
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
}

STM8S硬件I2C清除BUSY位.png (68.59 KB )

STM8S硬件I2C清除BUSY位.png

使用特权

评论回复
52
henangongda123|  楼主 | 2018-6-4 16:26 | 只看该作者
今天在查找资料,解决STM8S 硬件I2C BUSY位被置位的问题,感觉这篇**写的不错:
https://blog.csdn.net/dldw8816/article/details/51579781虽然是STM32,但是它和STM8S的I2C外设一样,晚上准备回去试试。

SWRST复位I2C.png (91.22 KB )

SWRST复位I2C.png

使用特权

评论回复
53
henangongda123|  楼主 | 2018-6-4 16:48 | 只看该作者
仔细看了下,ST官方这篇**和我遇到的BUSY位问题描述非常相似,感觉问题原因找到了,呵呵,晚上修改代码调试试试!

I2C 接口进入 Busy 状态不能退出.pdf

118.83 KB

使用特权

评论回复
54
henangongda123|  楼主 | 2018-6-5 21:33 | 只看该作者
根据上面的**,及各大网站网友的参考经验,现在程序加入BUSY防锁死操作后,效果好很多,每次MCU断电、通电,都可以看到硬件I2C信号正常(通过示波器观察),可奇怪的是,液晶显示器却不是每次都显示数字!?好奇怪。。。准备明天再找找原因

STM8S207 硬件I2C调试OK.png (329.19 KB )

STM8S207 硬件I2C调试OK.png

使用特权

评论回复
55
henangongda123|  楼主 | 2018-6-5 21:34 | 只看该作者
本帖最后由 henangongda123 于 2018-6-5 22:02 编辑

上传更新后的程序源代码:
/********* 硬件I2C操作 **********/
//初始化函数
/***********************************************************
函数名: I2C_Init()
功  能: STM8S207 MCU硬件I2C初始化
        (注: 主模式,两线连接,7位地址模式,10Kbps通信速率)
参  数: 无
返回值: 无
***********************************************************/
void I2C_Init(void)
{
  I2C_CR1 &= 0xFE;            //PE=0,禁用硬件I2C模块(所有位置0)
        CLK_PCKENR1 |= 0x01;        //使能I2C时钟
        I2C_CR2 |= 0x80;            //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
        I2C_CR2 &= 0x7F;            //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
  I2C_FREQR = 0x02;           //配置I2C外设时钟2MHz
        I2C_CCRH = 0x00;            //配置I2C为标准模式及速率
        I2C_CCRL = 0x64;            //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
        I2C_TRISER = 0x03;          //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
        I2C_CR1 |= 0x01;            //启动I2C硬件模块
}
//DS3231读取年、月、日、时、分、秒、星期等数据
/***********************************************************
函数名: DS3231_Read()
功  能: STM8S207 MCU通过硬件I2C通信读取DS3231内年月日时分秒等数据
参  数: data_buff --- 从DS3231读取的多字节数据指针
                          data_len  --- 从DS3231读取的多字节数据长度(7个)
返回值: 无
***********************************************************/
void DS3231_Read(uchar *data_buff,uchar data_len)
{         
        uchar temp;                 //定义一下,读取MCU状态寄存器用
        uchar i;                    //定义一下,供循环使用
        uint time;                  //定义一下,供等待延时用
        //以下程序为I2C通信防锁死操作,非常重要!
        if((PE_IDR&0x04) == 0x00)   //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
        {
                I2C_CR1 &= 0xFE;          //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
                PE_DDR |= 0x02;           //设置SCL端口为输出
                PE_CR1 |= 0x02;           //上拉输出
                for(i=0;i<9;i++)          //SCL端口发出9个时钟脉冲,让从设备DS3231释放总线(恢复SDA=1)
                {
                        PE_ODR &= 0xFD;         //SCL=0;
                        delay_us(50);           //延时(I2C通信频率10KHz)
                  PE_ODR |= 0x02;         //SCL=1
                  delay_us(50);           //延时(I2C通信频率10KHz)
                }
                time = 500;               //变量赋值,准备延迟等待500次
                while(!(PE_IDR&0x04))     //等待数据线SDA=1
                {
                  if(!--time)             //变量自减
                  return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
          }
                PE_DDR &= 0xFD;           //SCL端口恢复输入方式
                PE_CR1 &= 0xFD;           //浮空输入
                PE_ODR &= 0xFD;           //清零输出寄存器
                I2C_CR1 |= 0x01;          //重新启动硬件I2C模块,接管SCL、SDA端口
                return;                   //退出函数,放弃本次数据读取操作
        }
       //以上程序为I2C通信防锁死操作,非常重要!
        //以下程序为STM8S 硬件I2C通信防BUSY锁死操作,非常重要!

        if((I2C_SR3&0x02) == 0x02)  //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
        {
                I2C_CR2 |= 0x80;          //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
          I2C_CR2 &= 0x7F;          //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
                I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
                I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
                I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
          I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
                I2C_CR1 |= 0x01;          //启动I2C硬件模块
                return;                   //退出函数,放弃本次数据读取操作
        }
       //以上程序为STM8S 硬件I2C通信防BUSY锁死操作,非常重要!
        time = 500;                 //变量赋值,准备延迟等待500次
        while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD0;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=0表示写操作)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_DR = 0x00;              //发送DS3231寄存器地址(WORD ADDRESS,从00H到12H)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD1;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=1表示读操作)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_CR2        |= 0x04;            //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
        while(data_len)             //循环读取数据
        {
                if(data_len == 1)         //如果是接收最后一位数据(特殊处理)
                {
                        I2C_CR2 &= 0xFB;        //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
                        I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
                }
                if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
                {
                        *data_buff = I2C_DR;    //读取数据寄存器内数值,同时清除BTF位
                        data_buff++;            //准备接收下一字节数据
                        data_len--;
                }
        }
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
}

使用特权

评论回复
56
henangongda123|  楼主 | 2018-6-5 22:01 | 只看该作者
液晶显示器上电不显示的问题解决了,嘿嘿!原来是主程序里面初始化函数一次不太成功,多加了几次就OK了,哈哈//主函数
void main()
{
        Clk_Init();                 //系统时钟初始化
        Port_Init();                //端口初始化
        Lcd_Init();                 //12864液晶初始化
        I2C_Init();                 //硬件I2C初始化
        delay_ms(500);
        Lcd_Init();                 //12864液晶初始化
        Lcd_Init();                 //12864液晶初始化
        Lcd_Init();                 //12864液晶初始化


话说I2C通信真的跟有些网友反映的那样,好脆弱!有时候用手无意中碰到相关引脚都能引起通信紊乱,也是服了,好吧,就这样了,明天准备开始搞温湿度传感器SHT31,呵呵

使用特权

评论回复
57
springvirus| | 2018-6-6 10:11 | 只看该作者
宝贵的经验分享,顶楼主!!

使用特权

评论回复
58
henangongda123|  楼主 | 2018-6-6 11:33 | 只看该作者
springvirus 发表于 2018-6-6 10:11
宝贵的经验分享,顶楼主!!

使用特权

评论回复
59
henangongda123|  楼主 | 2018-6-6 17:29 | 只看该作者
今天焊废一片SHT31温湿度传感器,松香进传感器里面了,唉,浪费钱啊,14.5元一片!

使用特权

评论回复
60
henangongda123|  楼主 | 2018-6-6 17:44 | 只看该作者
重新买了焊接好的SHT31模块,晚上准备优化一下DS3231的程序,把修改日期的程序写一下。

SHT31模块.jpg (289.17 KB )

SHT31模块.jpg

使用特权

评论回复
发新帖 本帖赏金 5.50元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则