本次实验是在十三、LCD1602液晶屏驱动的基础上进行的功能扩展而成的,其工作的基本流程为:
外部RTC晶振32.768kHz的XT1和XT2通过RL78/G13的P12.3和P12.4管脚输入至RTC内作为RTC的工作时钟fRTC,这需要对外部RTC时钟做专门的设置,而这在前期的多个实验中都未曾用到,因此,这个地方也是最容易出错的地方,特专门对此用图来详解:
下面来上图,首先这张图是时钟Clock Generate工具箱关于Clock Setting的设置:
接下来这张图片是用来验证,你所设置的时钟是否正确,如果不是这样,就说明fSUB时钟选错了,应选择XT1 oscillation(fXT)。
接下来要上主函数图了,这个很关键,不要忘了启动固定时间中断,不然的话无法实时更新时间数据,如图所示:
接着是LCD读取时间数据的程序,这里采用了自动生成软件里定义的时间格式数据结构,这样调用起来比较方便,如图所示:
最后,是关键的实时时间数据更新的中断驱动程序,这里是使用固定时间中断的产生来实时更新时间数据显示的,如图所示:
最后来上图喽:
最后,再来个动态显示的视频:
http://v.youku.com/v_show/id_XNDQ0MzUyMjg0.html
十六、基于IICA0的EEPROM读和写
我的帖子有几天没有更新了,不是在忙别的,而是在忙着给自己充电,最近几天一直在学习IIC协议、RL78/G13中关于IICA0的Datasheet部分、EEPROM的读写等,在充分了解了它们的工作原理之后,这才通过编写程序,将其在硬件上实现出来,下面将关键的地方分享出来,希望能给EEPW友们以帮助,在这里仅起到抛砖引玉的作用。。。
本次实验的主要内容是通过RL78/G13内部的16位单片机控制其内部的IICA0(完全版的IIC)模块来实现对外部8KByte(1024个字节)的EEPROM进行读写实验。
首先,必备的知识是IIC总线传输协议,下图列出其工作时序图,供大家参考:
下一张是IIC协议外部接口SCL和SDA两个管脚与EEPROM的相应管脚连接是要注意接上拉电阻,如下图所示:
下图为RL78/G13datasheet中关于IIC协议(结合IICA0硬件电路)的时序流程图:
将以上三张图片结合起来看就是一个完整的发送(接收)流程图:由Start Condition~address~data~data~Stop Condition。
详细内容还请参考RL78/G13的datasheet的P770~P775,这上面对每一个过程都有详细的讲解,关键的难理解的地方还有详细的注释,这是进行本次试验要必看的。。。
下面要说的就是关于外部存储器EEPROM的基于IIC的具体是如何工作的,我本次试验采用的EEPROM的类型是:ATMEL113--24C08AN,其内部存储容量为8KByte(1024个字节),其写时序如下图:
读时序如下图:
还有一个很关键的地方,那就是当EEPROM通过IIC总线接收到来自RL78/G13传来的数据后,并不能瞬间就将数据存到其内部ROM里的,而是需要一定的操作时间,下表就给出了最小写周期,这在程序的编写过程中会有具体的体现。。。
有了这些基础知识做铺垫,接下来我们就可以顺利地进行基于软件CubeSuite+的编程了,首先来看一看自动代码生成器是如何设置的,具体设置如下图所示:
这一张是说明采用IICA0的完全版IIC的单主模式,设置如下图所示:
接下来这张图是关于IICA0的详细配置,具体设置如下图:
至于其它的工具箱和前面的几个实验用到的都没有太大的区别,这里仅给出一个用到的工具箱图:
好了,至此关于IICA0的设置基本已经完成,接下来要做的就是在自动生成的代码上添加程序即可,一些关键的代码如下图所示:
首先,帖出来一下有自动代码生成器自动生成的关于发送和接收两个函数的函数名,之所以在这里将其贴出,是因为,函数很容易理解,而关键在于如何给这两个函数赋值一直是一个很容易出错的地方(特别对C语言的指针理解不到的EEPW友们)。。。
这两个函数的函数名如下:
这里我们着重看那两个固定值指针,想想如何定义这两个指针呢,这使我想到了数组,还记得当时老师讲过,数组的数组名是可以退化为指针的,其就指向数组的起始地址,因此可以先定义一个含有若干元素的一维数组,然后就将数组名赋值给声明的指针即可(因为有const的存在,所以赋值要在变量声明中完成),具体的变量声明见下图:
接下来列出需要再serial函数中需要更改的地方,就是在发送和接收结束的函数中分别增加一个标志变量,以用来在主函数中判断读写状态十分完成,具体更改如下图所示:
下面就来张关键的主函数中是如何实现对外部EEPROM的读和写的,具体程序如下图所示:
这张是向EEPROM写数据的写函数:
具体过程是这样的,首先通过一个do--while循环来确保将数据send出去,然后紧接着判断标准位来确保数据发送完毕,最后是将发送的数据及其存储地址显示在LCD1602的第一行,具体的显示效果见后续的附图。
这是读函数的过程,看上去比写函数的过程要来的复杂,实际上也确实如此,因为要想从EEPROM读数据,首先就要先向EEPROM写数据以便告知EEPROM准备要从哪个地址开始读数据,但大原理与写过程类似,这里就不赘述了。。。
最后来张本实验用到的工具箱图,因为其它工具箱的使用在前面已有详细的介绍,这里也就不赘述了。。。
最后要上图了,接下来的两张图是演示,先通过IIC总线向EEPROM的00地址单元写入数据111,并通过IIC总线将其读出显示在LCD1602上的过程。。。
接下来的两张图是演示,通过更改源程序中的数据通过IIC总线向EEPROM的地址025单元写入数据236,并通过IIC总线将其读出显示在LCD1602上的过程。。。
上视频链接喽。。。
http://v.youku.com/v_show/id_XNDQ3MjA4Mjg0.html
十七、PWM模块实现H桥直流电机驱动
本次试验又是一个新模块的实验,本实验的大致工作流程使这样的:
1、有五个按钮,以中断的方式分别控制电机的五个基本状态:正转(+ run)、反转(- run)、停止(stop)、加速(+ speed)和减速(- speed)。通过这五个基本状态的组合还有正转加速、反转加速等,通过H桥电路对直流电机的运行状态进行全方位的控制。说到H桥电路,下面我先说一下H桥电路的基本电路图及其工作原理:
下图所示为一个典型的直流电机控制电路:
下图所示为电机朝一个方向旋转的示意图:
下图所示是电机朝另一个方向旋转的示意图:
下图为典型的实用的H桥电路图:
本次实验用到的H桥电路图如下图所示:
以上为科普知识。。。未完待续。。。。
大家可以先看看视频,一睹为快,链接地址如下:
http://v.youku.com/v_show/id_XNDQ4MTk0ODMy.html
十七、PWM模块实现H桥直流电机驱动
本次实验用到的模块:
1:RL78/G13核心开发板:产生2路PWM波驱动H桥直流电机驱动电路
2:LCD1602液晶显示器:显示直流电机的运行状态和占空比
3:H桥直流电机驱动电路:实现对电机的正反转控制
4:直流电机:型号为:N13LB110
本次实验的CubeSuite+编程及设置:
本次实验的Timer模块使用到的通道情况如下:
本次实验的PWM主从通道设置方式,(每一路PWM波就需要2路通道,本次实验采用2和3一组,4和5一组),通道的搭配选择是有讲究的,具体是这样的:
通道0、2、4、6可以作为主通道使用,通道1至7可以作为从通道使用,但是还要有一个条件:
从通道的通道号一定要大于主通道的通道号,例如:若选2通道为主通道,则只有3、4、5、6、7可以与通道2配合作为其从通道,而通道1却不可以,还有一个规则:
从通道与主通道之间不可有另外一个主通道,例如:若选2、4分别为2个PWM生成器的主通道,则通道5、6、7不可作为通道2的从通道,因为中间有一个通道4为另外一个主通道。
详细内容请参考RL78/G13的datasheet的第359页:时钟单元的基本规则,这里对其有详细的描述,下面上个图参考一下先:
下面上图:第一个PWM模块的主通道Channel2设置:
第一个PWM模块的从通道Channel3设置:
第二个PWM模块的主通道4的设置与通道2的设置完全相同,从通道5的设置与通道3的设置完全相同。
PWM的周期和占空比计算方式如下图所示:
5个中断按键的中断函数如下程序所示:
__interrupt static void r_key_interrupt(void)
{
/* Start user code. Do not edit comment generated here */
switch (P6)
{
case 254: key0input =1; //the key name is "- run".
duty2Period = 0; //the output of PWM2 is duty=0% (PWM2==0) PWM wave.
cycle2Period = 3199;
duty4Period = 1600; //the output of PWM4 is duty=50% PWM wave.
cycle4Period =3199;
//LCD_dispkey0();
break;
case 253: key1input =1; //the key name is "stop"
duty2Period = 3200;
cycle2Period = 3199; // the output of both TO03 and TO05 is "1", so the motor is "stop".
duty4Period = 3200;
cycle4Period = 3199;
break;
case 251: key2input =1; //the key name is "+ run".
duty2Period = 1600; //the output of PWM2 is duty=50% PWM wave.
cycle2Period = 3199;
duty4Period = 0; //the output of PWM4 is duty=0% (PWM4==0) PWM wave.
cycle4Period = 3199;
break;
case 247: key3input =1; //the key name is "- speed".
if (duty2Period == 0)
{
if (duty4Period > 50) //when the PWM4 is the engine, decrease the duty of PWM4.
{
duty4Period = duty4Period - 50;
}
else
{
duty4Period = 0; //the speed minium is "0" always ("stop").
}
}
else if ( duty4Period == 0)
{
if (duty2Period > 50) //when the PWM2 is the engine, decrease the duty of PWM2.
{
duty2Period = duty2Period - 50;
}
else
{
duty2Period = 0; //the speed minium is "0" always ("stop").
}
}
else
{
duty2Period = cycle2Period + 1; //put the output of both PWM2 and PWM4 high level "1".
duty4Period = cycle4Period + 1; //then the motor will "stop".
}
break;
case 239: key4input =1; //the key name is "+ speed".
if (duty2Period == 0)
{
if (duty4Period < cycle4Period -49) //when the PWM4 is the engine, increase the duty of PWM4.
{
duty4Period = duty4Period + 50;
}
else
{
duty4Period = cycle4Period + 1; //the speed maxium is "1" always.
}
}
else if ( duty4Period == 0)
{
if (duty2Period < cycle2Period -49) //when the PWM2 is the engine, increase the duty of PWM2.
{
duty2Period = duty2Period + 50;
}
else
{
duty2Period = cycle2Period + 1; //the speed maxium is "1" always.
}
}
else
{
duty2Period = cycle2Period + 1; //put the output of both PWM2 and PWM4 high level "1".
duty4Period = cycle4Period + 1; //then the motor will "stop".
}
break;
default:
{
//duty2Period = cycle2Period + 1; //put the output of both PWM2 and PWM4 high level "1".
//duty4Period = cycle4Period + 1; //then the motor will "stop".
}
}
KRIF=0; //clear the flag of the keyinterrupt
/* End user code. Do not edit comment generated here */
}
Timer的占空比更新程序,由于Timer中TDR的更新只能在主通道中断产生之后,而且要求中断产生后要立即更新,所以就将TDR02和TDR03的数据更新放在了通道2的中断函数内,如下程序:
__interrupt static void r_tau0_channel2_interrupt(void)
{
/* Start user code. Do not edit comment generated here */
TDR02=cycle2Period;
TDR03=duty2Period;
/* End user code. Do not edit comment generated here */
}
另一个PWM的中断函数与之类似,如下所示:
__interrupt static void r_tau0_channel4_interrupt(void)
{
/* Start user code. Do not edit comment generated here */
TDR04=cycle4Period;
TDR05=duty4Period;
/* End user code. Do not edit comment generated here */
}
最后,说一下本次试验PWM波输出的两个管脚分别为:P31:TO03、P05:TO05
接下来上几张效果图:
系统搭建组装图:
直流电机旋转中图:
LCD1602显示电机运行状态图:
LCD1602显示数据的格式如下:
第一路PWM的占空比(%) 正转(+)/反转(-) 常显字符“run”
第二路PWM的占空比(%) 加速(+)/减速(-) 常显字符“speed”
好了,最后上个视频链接:
http://v.youku.com/v_show/id_XNDQ4MTk0ODMy.html
好的,期待着EEPW友们提出改进意见,更期待着你们的作品。。。一起分享。。。共同学习。。。
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |