BM8563是一款低功耗CMOS实时时钟/日历芯片,它提供一个可编程的时钟输出,一个中断输出和一个掉电检测器,所有的地址和数据都通过I2C总线接口串行传递。最大总线速度为400Kbits/s,每次读写数据后,内嵌的字地址寄存器会自动递增。
BM8563有16个寄存器,其中11个是BCD格式。配置是要注意值范围,不能超出。更多具体应用请看官方手册。
晶振选择非常重要。32.768不用说了,主要是ESR值,不能小了,也不能太大。按照厂家给出的30K肯定可以启振并稳定振荡。负载电容建议6pf,其实芯片内部已经接了一个负载电容,外面的负载电容是用来微调秒走时的准确性的。
特别提出,不要使用贴片的那种小的晶振,那种ESR才几十个欧姆,BM8563由于需要低功耗,所以输出的激励也很小,根本不能使这种低ESR的晶振启振。一定要按照官方给出的30K欧姆来选择晶振。
晶振接的两个电容是调整秒针精度的。如果没有专业仪器调整,那就按官方建议的6pF和19pF,走时也不会太差。
SDA和SCL两根线必须加上拉电阻,4.7K或者10K即可。STM32对应管脚需配置成开漏输出模式。
下面代码是按照官方手册C代码进行修改来的,在STM32RCT6单片机上测试通过,
需要的可以直接复制拿去。一开始我也下载了其他代码,看起来很全面,但是却不好用,IIC部分时钟有点问题,读出数据是不对的。最后直接参照官方手册,写了下面代码。
#include "iic.h"
uint8_t twdata[9]={
0x00,0x00,0x50,0x59,0x23,0x31,0x06,0x12,0x04};/*前2个数据用来设
置状态寄存器,后 7 个用来设置时间寄存器 */
uint8_t trdata[7]={
0}; /*定义数组用来存储读取的时间数据 */
uint8_t asc[14]={
0}; /*定义数组用来存储转换的 asc 码时间数据,供显示用 */
volatile uint8_t ack = 0;
volatile uint8_t bm_status = 0;//如果BM时钟芯片无应答,则为0,。应答正常则为1.
void IIC_SDA_SET(void)
{
HAL_GPIO_WritePin(BM8563_SDA_GPIO_Port,BM8563_SDA_Pin,GPIO_PIN_SET);
}
void IIC_SDA_RESET(void)
{
HAL_GPIO_WritePin(BM8563_SDA_GPIO_Port,BM8563_SDA_Pin,GPIO_PIN_RESET);
}
void IIC_SCL_SET(void)
{
HAL_GPIO_WritePin(BM8563_SCL_GPIO_Port,BM8563_SCL_Pin,GPIO_PIN_SET);
}
void IIC_SCL_RESET(void)
{
HAL_GPIO_WritePin(BM8563_SCL_GPIO_Port,BM8563_SCL_Pin,GPIO_PIN_RESET);
}
uint8_t IN_SDA(void)
{
if(HAL_GPIO_ReadPin(BM8563_SDA_GPIO_Port,BM8563_SDA_Pin))
{
return 1;
}
else
{
return 0;
}
}
/******************************************************************************
* Function Name --> IIC启动
* Description --> SCL高电平期间,SDA由高电平突变到低电平时启动总线
* SCL: __________
* \__________
* SDA: _____
* \_______________
* Input --> none
* Output --> none
* Reaturn --> none
******************************************************************************/
void IIC_Start(void)
{
IIC_SDA_SET(); //为SDA下降启动做准备
Delay_1us();
IIC_SCL_SET(); //在SCL高电平时,SDA为下降沿时候总线启动
Delay_Nus(10);
IIC_SDA_RESET(); //突变,总线启动
Delay_Nus(10);
IIC_SCL_RESET();
Delay_Nus(2);
}
/******************************************************************************
* Function Name --> IIC停止
* Description --> SCL高电平期间,SDA由低电平突变到高电平时停止总线
* SCL: ____________________
* __________
* SDA: _________/
* Input --> none
* Output --> none
* Reaturn --> none
******************************************************************************/
void IIC_Stop(void)
{
IIC_SCL_RESET();
Delay_1us();
IIC_SCL_SET(); //在SCL高电平时,SDA为上升沿时候总线停止
Delay_Nus(10);
IIC_SDA_SET(); //突变,总线停止
Delay_Nus(10);
}
/******************************************************************************
* Function Name --> 主机向从机发送应答信号
* Description --> 每从 BM8563 读取一个字节数据后都要发送应答信号
* Input --> a:应答信号
* 0:应答信号
* 1:非应答信号
* Output --> none
* Reaturn --> none
******************************************************************************/
void IIC_Ack(uint8_t a)
{
if(a) IIC_SDA_SET(); //放上应答信号电平
else IIC_SDA_RESET();
Delay_Nus(10);
IIC_SCL_SET(); //为SCL下降做准备
Delay_Nus(10);
IIC_SCL_RESET(); //突变,将应答信号发送过去
Delay_Nus(2);
}
/******************************************************************************
* Function Name --> 向IIC总线发送一个字节数据
* Description --> 向 BM8563 写一个字节的数据
* Input --> dat:要发送的数据
* Output --> none
* Reaturn --> ack:返回应答信号
******************************************************************************/
void IIC_Write_Byte(uint8_t dat)
{
uint8_t i;
for(i=0;i<8;i++)
{
if((dat<<i)&0x80)
{
IIC_SDA_SET(); //判断发送位,先发送高位
}
else
{
IIC_SDA_RESET();
}
Delay_1us();
IIC_SCL_SET(); //为SCL下降做准备
Delay_Nus(10);
IIC_SCL_RESET(); //突变,将数据位发送过去
} //字节发送完成,开始接收应答信号
Delay_Nus(2);
IIC_SDA_SET(); //释放数据线
Delay_Nus(2);
IIC_SCL_SET(); //为SCL下降做准备
Delay_Nus(4);
if(IN_SDA())//读取应答信号
{
ack = 0;
}
else
{
ack = 1;
}
IIC_SCL_RESET();
Delay_Nus(2);
}
/******************************************************************************
* Function Name --> 从IIC总线上读取一个字节数据
* Description --> none
* Input --> none
* Output --> none
* Reaturn --> x:读取到的数据
******************************************************************************/
uint8_t IIC_Read_Byte(void)
{
uint8_t i;
uint8_t rect=0;
IIC_SDA_SET(); //首先置数据线为高电平
for(i=0;i<8;i++)
{
Delay_1us();
IIC_SCL_RESET();
Delay_Nus(10);
IIC_SCL_SET();
Delay_Nus(2);
rect=rect<<1;
if(IN_SDA())
{
rect=rect+1;
}
Delay_Nus(2);
}
IIC_SCL_RESET();
Delay_Nus(2);
return rect; //返回读取到的数据
}
/********************************************************************
函 数 名: GetBM8563(void)
功 能:从 BM8563 的内部寄存器(时间、状态、报警等寄存器)读取数据
说 明:该程序函数用来读取 BM8563 的内部寄存器,譬如时间,报警,状态等寄存器
采用页写的方式,设置数据的个数为 no,no 参数设置为 1 就是单字节方式
调 用:Start_I2C(),SendByte(),RcvByte(),Ack_I2C(),Stop_I2C()
入口参数:sla(BM8563 从地址), suba(BM8563 内部寄存器地址)
*s(设置读取数据存储的指针), no(传输数据的个数)
返 回 值:有,用来鉴定传输成功否
***********************************************************************/
uint8_t GetBM8563(uint8_t sla,uint8_t suba,uint8_t *s,uint8_t no)
{
uint8_t i;
IIC_Start();
IIC_Write_Byte(sla);
if(ack==0)return(0);
IIC_Write_Byte(suba);
if(ack==0)return(0);
IIC_Start();
IIC_Write_Byte(sla+1);
if(ack==0)return(0);
for(i=0;i<no-1;i++)
{
*s=IIC_Read_Byte();
IIC_Ack(0);
s++;
}
*s=IIC_Read_Byte();
IIC_Ack(1);
IIC_Stop();//除最后一个字节外,其他都要从 MASTER 发应答。
return(1);
}
/********************************************************************
函 数 名:SetBM8563(void)
功 能:设置 BM8563 的内部寄存器(时间,报警等寄存器)
说 明:该程序函数用来设置 BM8563 的内部寄存器,譬如时间,报警,状态等寄存器
采用页写的方式,设置数据的个数为 no,no 参数设置为 1 就是单字节方式
调 用:Start_I2C(),SendByte(),Stop_I2C()
入口参数:sla(BM8563 从地址), suba(BM8563 内部寄存器地址)
*s(设置初始化数据的指针), no(传输数据的个数)
返 回 值:有,用来鉴定传输成功否
***********************************************************************/
uint8_t SetBM8563(uint8_t sla,uint8_t suba,uint8_t *s,uint8_t no)
{
uint8_t i;
IIC_Start();
IIC_Write_Byte(sla);
if(ack==0)return(0);
IIC_Write_Byte(suba);
if(ack==0)return(0);
for(i=0;i<no;i++)
{
IIC_Write_Byte(*s);
if(ack==0)return(0);
s++;
}
IIC_Stop();
return(1);
}
/********************************************************************
函 数 名:void Bcd2asc(void)
功 能:bcd 码转换成 asc 码,供液晶显示用
说 明:
调 用:
入口参数:
返 回 值:无
***********************************************************************/
void Bcd2asc(void)
{
uint8_t i,j;
for (j=0,i=0; i<7; i++)
{
asc[j++] =(trdata[i]&0xf0)>>4|0x30 ;/*格式为: 秒 分 时 日 月 星期 年 */
asc[j++] =(trdata[i]&0x0f)|0x30;
}
}
/********************************************************************
函 数 名:datajust(void)
功 能:将读出的时间数据的无关位屏蔽掉
说 明:BM8563 时钟寄存器中有些是无关位,可以将无效位屏蔽掉
调 用:
入口参数:
返 回 值:无
***********************************************************************/
void datajust(void)
{
trdata[0] = trdata[0]&0x7f;
trdata[1] = trdata[1]&0x7f;
trdata[2] = trdata[2]&0x3f;
trdata[3] = trdata[3]&0x3f;
trdata[4] = trdata[4]&0x07;
trdata[5] = trdata[5]&0x1f;
trdata[6] = trdata[6]&0xff;
}
/********************************************************************
函 数 名:Set_Start_BM8563(void)
功 能:配置启动BM8563
说 明:
调 用:
入口参数:
返 回 值:无
***********************************************************************/
void Set_Start_BM8563(void)
{
printf_sz_hex(twdata,9);
do
{
bm_status = SetBM8563(0xa2,0x00,twdata,0x09);//设置时间和日期
printf("设置时间\r\n");
printf_sz_hex(twdata,9);
}
while(bm_status==0);
printf("设置成功\r\n");
}
下面是printf重定向到串口,串口输出十六进制数组函数。
/*重定义Printf函数到串口3*/
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart3,(uint8_t *)&ch,1,0xFFFF);
return ch;
}
/*以十六进制格式输出数组*/
void printf_sz_hex(uint8_t *pdata,uint32_t len)
{
printf("\r\n");
for(uint32_t i=0;i<len;i++)
{
printf("%02X ", *(pdata+i));//十六进制格式输出,两位,高位没有则补0,X字母大写,x字母小写
}
printf("\r\n");
}
然后在main函数里调用void Set_Start_BM8563(void)即可。
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
HAL_Delay(1000);
Set_Start_BM8563(); //设置时间、日期
while (1)
{
HAL_Delay(1000);
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
do{
bm_status=GetBM8563(0xa2,0x02,trdata,0x07);//测试读取时间、日期
}
while(bm_status==0);
datajust();
Bcd2asc();
printf_sz_hex(asc,14); //打印时间、日期
}
}
串口助手每秒打印输出一次时间日期。可以看出,读出来的秒是走的。开始时用贴片3225封装的32.768K晶振,怎么弄也不走,最后查了手册需要30K欧ESR的晶振,然后又采购换上了这种圆柱体的,测试很稳定。
最后,如果晶振不起振,IIC一样可以读写寄存器,读写寄存器不依赖32.768K晶振。
遇到什么问题,一定要仔细阅读官方手册。也欢迎大家交流。
文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态
文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境
文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn
文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker
文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机
文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk
文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入
文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。 Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。
文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动
文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计
文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;gt;Jni-&amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图
文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法