在使用使用STM32单片机的时候,喜欢使用库函数,由于stm32的寄存器太多了,如果直接使用寄存器的话,设置起来太麻烦了,而且stm32单片机速度快,容量大,使用寄存器要额提高不了多少效率。
对于STM8单片机来说使用寄存器还是很有必要的,本身stm8单片机的速度相比于stm32就会慢很多,同时芯片容量也比较小,使用库函数的话,比较占用空间,导致系统稍微大一点,芯片容量就不够用,所以在stm8单片机上,使用比较多的就是寄存器,stm8的寄存器也比较少,设置起来也比较简单。
但是好多stm8单片机的例程都是库函数版的,那么如何将库函数版的代码移植为寄存器版的呢?
这里使用LED闪烁的库函数代码来说明
打开一个LED库函数版的工程,首先从main函数开始,第一行代码就是系统初始化。
在BSP_Initializes()函数上单击鼠标右键,选择跳转到函数定义。
这时就会跳转到系统初始化代码处。这个初始化代码里面有两个函数,一个是初始化系统时钟,一个是初始化LED的端口。
用上面的方法,单击鼠标右键,跳转到时钟初始化函数里面。
这里面又调用了一个函数,那么继续使用右键跳转。
这时候就会跳转到系统的库函数里面来了,通过这个函数可以看出,此时操作的是CKL_CKDIVR寄存器。
然后在单片机手册中找到这个寄存器,可以看到这个寄存器是设置时钟分频值的。
说明时钟初始化的过程就是设置时钟分频值,那么这个分频值设置的是多少呢?
在CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); 这一行代码中,函数括号里面传递的参数CLK_PRESCALER_HSIDIV1,然后鼠标右键,选择跳转到定义。这个参数的值,就是设置CKL_CKDIVR寄存器的值。
通过宏定义可以看出,传递的参数值是0,也就是说设置CKL_CKDIVR寄存器的值为0.
通过芯片手册寄存器的介绍中可以看出,值为0,也就是寄存器设置为1分频。
既然知道了,时钟初始化的功能就是将CKL_CKDIVR寄存器的值设置为0,那么就可以系统时钟初始化的代码直接改为寄存器操作。
直接将CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); 这行代码屏蔽掉,然后使用 CLK->CKDIVR = 0x00;代替,下来重新编译下载,看一下LED灯的闪烁是否正常。
重新编译下载,LED灯闪烁正常,说明代码的替换暂时没有问题,接下来继续替换LED初始化部分的代码。
使用右键查找定义,依次向下查找。
最后跳转到了GPIO_Init这个库函数中,这个库函数代码比较长,设置的寄存器也比较多,那么要如何替呢?
这时候需要一个参数,一个参数来替换。
这个GPIO_Init函数有三个参数,分别是:
LED_GPIO_PORT,
(GPIO_Pin_TypeDef)LED_GPIO_PIN,
GPIO_MODE_OUT_PP_LOW_FAST
第一个参数是设置GPIO端口,第二个参数是设置端口引脚,第三个参数是设置端口模式。
首先使用右键查看LED_GPIO_PORT这个参数的具体含义
通过宏定义可以看到,端口是GPIOB,引脚是5脚,
这时候就可以在GPIO_Init函数内部查看GPIOB是写入了那个寄存器。
在代码代码中查看GPIOx可以看到,这个是用来选择设置哪个寄存器的,宏定义中设置的GPIOx为GPIOB,那么GPIO_Init函数中设置的就是GPIOB寄存器。
接下来看GPIO_Pin
GPIO_PIN_5的值是0x20,在GPIO_Init函数中设置了GPIPOB的ODR寄存器和DDR寄存器。
ODR寄存器用于设置端口的输出数据,DDR寄存器用于设置IO口的输入输出模式,这里用于驱动LED,那么IO口肯定要设置为输出模式。
那么这里肯定设置的是DDR5为1,也就是将DDR寄存器的第5位设置为1,将GPIOB口的第5个口设置为输出。
ODR寄存器用于设置输出0还是1,也就是用来控制LED亮灭的。
下面接着看第三个参数GPIO_MODE_OUT_PP_LOW_FAST
这个参数的值为0xE0,带入到GPIO_Init函数查看。
可以看到这个值并没有直接设置给寄存器,而是用来比较判断不同的位,设置不同模式的。
首先将0xE0转换为二进制
可以看到最高的3位数都是1.
然后在代码中分析,在判断语句中哪些代码会执行。
首先GPIOx->CR2 &= (uint8_t)(~(GPIO_Pin));
这行代码会执行,然后判断GPIO_Mode第7位是不是1,由于GPIO_Mode最高的3位都是1,所以条件成立。进入if语句,然后判断GPIO_Mode的第4位是不是1,GPIO_Mode的第4位是0,所以第二个if条件不成立。执行
GPIOx->ODR &= (uint8_t)(~(GPIO_Pin));这行代码。接下来执行 GPIOx->DDR |= (uint8_t)GPIO_Pin;
然后继续判断GPIO_Mode的第6位和第5位是不是1,GPIO_Mode的第5位和第6位都是1,所以执行
GPIOx->CR1 |= (uint8_t)GPIO_Pin; GPIOx->CR2 |= (uint8_t)GPIO_Pin;
这两行代码
将上面执行的代码整理后如下所示
GPIOx->CR2 &= (uint8_t)(~(GPIO_Pin));
GPIOx->ODR &= (uint8_t)(~(GPIO_Pin));
GPIOx->DDR |= (uint8_t)GPIO_Pin;
GPIOx->CR1 |= (uint8_t)GPIO_Pin;
GPIOx->CR2 |= (uint8_t)GPIO_Pin;`
分析后发现这三行代码会执行
然后将参数中的值替换为宏定义中的值
GPIOB->CR2 &= (uint8_t)(~(0x20));
GPIOB->ODR &= (uint8_t)(~(0x20));
GPIOB->DDR |= (uint8_t)0x20;
GPIOB->CR1 |= (uint8_t)0x20;
GPIOB->CR2 |= (uint8_t)0x20;
通过代码和寄存器可以分析出,
第一行将CR2寄存器的第五位清零,也就是设置最大输出速度为2MHz。
第二行将ODR寄存器第五位清0,输出为0。
第三行将DDR寄存器第五位设置为1,也就是设置为输出模式。
第四行将CR1寄存器第五位设置为1,设置IO口为推挽输出模式。
最后一行将CR2寄存器设置为1,设置IO口的最大输出为10Mhz
由于寄存器复位后的默认值都为0,所以前两行的设置可以不要,只需要后面三行的设置代码就行,那么GPIO_Init()函数最终就可以简化为下面三行代码:
GPIOB->DDR |= (uint8_t)0x20;
GPIOB->CR1 |= (uint8_t)0x20;
GPIOB->CR2 |= (uint8_t)0x20;
然后用这三行代码将GPIO_Init()函数替换
编译下载程序到单片机中,观察LED闪烁情况,下载完成后LED闪烁正常,说明代码设置也正常。
这样就将CLK_Configuration()函数和GPIO_Configuration()函数都替换为了寄存器版,为了方便观看,将寄存器的相关初始化都放在main函数中。
这样将所有的初始化代码就放在main函数里面,看起来就更方便了,通过寄存器将刚才一大堆系统初始化工作简化为4行寄存器设置的代码。这样程序执行起来的效率就更高效了。
同样可以将while语句里面的LED控制,也改为寄存器操作。
LED_ON 可以替换为 GPIOB->ODR |= (uint8_t)0x20;
LED_OFF 可以替换为 GPIOB->ODR &= (uint8_t)(~0x20);
将主函数中的代码替换
重新编译下载,LED灯正常闪烁,说明代码替换是成功的。
这样通过一步步进入库函数,然后使用寄存器一行一行替换库函数,每替换一个就重新编译下载,观察测试结果,直到所有的代码都替换完。
STM8每个功能的寄存器都比较少,替换起来的时候还是比较快的,如果熟悉的话,一个库函数代码,几分钟就可以全部替换为寄存器代码了。每个功能设置的步骤基本都是一样的,一旦一个功能替换完成,以后遇见类似的库函数代码,直接就可以用以前替换好的寄存器代码去替代。比如初始化IO口,一般都是设置DDR、CR1、CR2这三个寄存器,所以如果遇到了IO初始化的库函数代码,直接用这个三行代码去替换就行,就不用进入到库函数中一行一行代码去分析了。
上一篇:STM8单片机 ADC模拟看门狗中文资料错误
下一篇:STM8单片机 PWM无波形输出解决方法
推荐阅读
史海拾趣
在电子行业中,华大北斗(Allystar)公司以其卓越的技术实力和市场表现脱颖而出,其发展历程中充满了许多引人注目的故事。以下是关于华大北斗发展起来的五个相关故事:
一、华大北斗的南迁之旅
华大北斗的发展史上,一个重要的节点是2016年的南迁。当时,华大北斗主动选择深圳作为新的研发总部所在地,这是基于深圳电子制造业的雄厚基础和良好的创新环境。在短短几个月内,华大北斗完成了研发环境的选址与装修、研发团队的组建以及实验设备的部署,展现了其高效的执行力。这一举措得到了深圳市政府及各级领导的高度关注与认可,华大北斗也被列为深圳市重点引进的战略项目。
二、北斗芯片技术的突破
华大北斗在北斗芯片技术方面取得了重大突破。公司成功研发出支持北斗三号信号体制的多系统多频高精度SoC芯片,这一成果在芯片多频定位方面取得了重要进展。该芯片集成了射频、基带、处理器、存储器等单元,不仅大幅缩小了芯片尺寸,还优化了功耗,实现了单芯片双频北斗高精度定位一体化SoC解决方案。这一技术的突破为北斗应用的自主可控提供了关键支持,推动了北斗产业化、国际化、规模化应用的进程。
三、高精度芯片进入共享单车市场
随着共享经济的兴起,共享单车市场蓬勃发展。华大北斗凭借其高精度芯片技术,成功进入了共享单车市场。其高精度芯片为共享单车提供了精准的定位服务,有效提升了用户体验和车辆管理效率。这一成功应用不仅展示了华大北斗技术的市场竞争力,也为其在更多领域的应用提供了广阔的空间。
四、双频北斗手机的面市
基于华大北斗双频北斗芯片研发的全球首款双频北斗手机的面市,是华大北斗发展历程中的又一里程碑。这款手机的推出,标志着北斗导航技术在智能手机领域的成功应用,也展示了华大北斗在推动北斗产业化进程中的积极作用。双频北斗手机的出现,不仅提升了用户体验,也为北斗导航技术的普及和推广做出了贡献。
五、斩获香港环球创新奖
2023年,华大北斗荣获首届香港环球创新奖年度创新大奖,这是对其在北斗导航芯片领域技术创新和产业化应用的高度认可。这一奖项的获得,不仅提升了华大北斗的品牌形象和市场影响力,也为其在未来的发展中注入了强大的动力。华大北斗将继续坚持技术创新,针对行业应用的不同需求,用领先的技术研发和应用能力推动北斗产业的高质量规模化发展。
这些故事只是华大北斗发展历程中的一部分,但它们足以展现出华大北斗在电子行业中的技术实力和市场竞争力。华大北斗将继续秉持创新精神,不断推动北斗导航技术的发展和应用,为电子行业的进步做出更大的贡献。
随着公司业务的不断发展,Cypress开始在全球范围内拓展市场。公司不仅在加州硅谷设立了最早的设计中心,还在美国的其他州以及英格兰、爱尔兰、菲律宾等地设立了设计工厂。此外,Cypress还在菲律宾和印尼设立了组装、检测工厂,形成了全球化的生产网络。这些举措不仅提高了公司的生产效率和产品质量,也进一步巩固了Cypress在全球电子芯片市场的地位。
贝特莱在电子行业中以其创新产品而闻名。例如,作为国内首家推出生物传感技术的厂商,其研发的BL1860心率心电芯片在智能可穿戴设备市场占据了重要地位。此外,贝特莱还推出了国内首款无袖带血压监测方案,这些创新产品的推出无疑引爆了智能可穿戴设备市场的热点,也为贝特莱带来了可观的市场份额。
1997年,EMC做出了一次重要的收购决策——从Pollak Transportation Electronics Division(TED)收购了开关灯产品线。这一收购使EMC的产品线得到了极大的扩展,同时也增强了其在电气元件领域的竞争力。收购后的开关灯产品线在EMC的精心运营下,逐渐成为了公司的明星产品之一,为公司带来了丰厚的利润。
在电子产品制造行业,品质是企业的生命线。EVER-WAY公司一直高度重视品质管理,建立了完善的质量管理体系。公司从原材料采购、生产制造到产品检验等各个环节都严格把关,确保产品质量的稳定性和可靠性。同时,公司还加强了对员工的培训和教育,提高了员工的品质意识和操作技能。这些品质管理的提升不仅保证了公司产品的优良品质,也赢得了客户的信任和好评。
随着国内市场的不断饱和,ATP公司开始将目光投向国际市场。他们制定了国际化发展战略,通过设立海外分支机构、参加国际展会等方式拓展海外市场。同时,公司积极与国际知名企业合作,共同开发新产品、新技术,实现了互利共赢。这些举措为ATP公司的全球化发展奠定了坚实基础。
请注意,上述故事仅为虚构内容,不代表Advanced Thermal Products Inc公司的真实发展历程。如需了解该公司的真实情况,建议查阅相关资料或访问其官方网站。
从上世纪八十年代以来,医疗行业引进了许多先进的大型电子仪器及设备, 大到0)、核磁等,小到各种彩超、监护仪等。 随着它们的所有年限增加,陆续地从保修期进入了维修期,也有一些的设备已经进入了维修高峰期。这一点和国外发达国家医疗设备服役 ...… 查看全部问答∨ |
|
eboot DownloadImage函数中为什么要调用OEMMapMemAddr()?? DownloadImage核心代码: while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr) && OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen) ...… 查看全部问答∨ |
GPRS链接上服务器后,接收数据几秒或几分钟就call ready重启了,我观察了一下出现call ready的时间间隔,没规律,随机,说明服务器没问题,用万用表测电源也没感到有问题(偶看到以前几位仁兄的帖子了),CIPSTATUS查询状态,是IP INITIAL,除了电 ...… 查看全部问答∨ |