一、开发环境介绍
CS+ for CACX: 瑞萨单片机开发环境,已经停止更新,含有图形化配置工具,免费。 CS+ for CC: 瑞萨单片机开发环境,未来主推的开发环境,含有图形化配置工具,收费,适合财力雄厚的开发者。(其实用CACX足以) IAR for RL78: 瑞萨单片机开发环境,IAR推出的RL78系列的开发环境,寄存器编程,不集成图形化配置工具。 AP4 for RL78_EC:瑞萨单片机独立图形化配置工具,是单独的一个软件,把生成的代码导入到工程里即可。 注1:瑞萨单片机型号有中国区的,中国区的一般在开发环境中看不到型号,需要首先导入设备文件才能看到。 注2:本单片机入门教程基于 CS+ for CACX(开发环境) 和 R7F0C004 (MCU型号)进行讲解,为入门解决各种头疼的问题。
二、下载与仿真器的选择
瑞萨单片不像STM32一样内部有boot程序,所以裸机情况下不支持串口下载。IECUBE、E2 Lite 、E1 、E20 、EZ均为瑞萨单片机的下载&仿真器,其中E1功能最多,但也非常昂贵,好几千的价格。E2 Lite是E2的硬件简化版本,网上有很多自己制作的,一个也就卖一二百,建议使用这款,去某宝购买的时候,名字可不是E2 Lite,而是EZ CUBE2,所以花费200左右去某宝买一个EZ CUBE2就可以完成下载和仿真的工作了。(软件中没有EZ CUBE2,只 有E2 Lite,设置仿真器为E2 Lite即可,废话不多说,上图)
三、CS+ for CACX软件安装
CS+ for CACX安装非常简单,也不需要破解,一直点同意&下一步即可完成安装,这里不在赘述。 如需软件安装包和MCU支持包,可以去瑞萨官网自行下载、或者加全国大学生电子交流QQ群649692007下载、5积分下载。 MCU支持包安装方式如下: CSPlus_CACX_Package_V40500.7z <===点击此处下载CS+ FOR CACX,仅需5积分
R7F0C001_002_003_004_019_MCU设备文件.zip <===点击此处下载MCU设备文件,仅需5积分
四、新建工程
说明:但凡通过添加支持包的MCU型号在软件中都不支持图形化配置,需要用AP4生成后导入,由于R7F0C004M和R5F10WMG几乎完全一样,R7F0C004M仅是在R5F10WMG的基础上阉割了一两个外设而已,为了使用CACX内部的集成配置工具,这里使用R5F10WMG进行建立工程,多出的外设不配置,直接关闭即可。(以下是特别全乎的建工程模板的教程,可以避免很多CACX软件BUG带来的问题—原创哦)
至此,工程建立完成,建议按照图片教程配置,会省去很多不必要的麻烦(不要感谢我,我只会个helloworld,收藏一下我吧) CACX软件只能函数跳转,不能变量跳转,只能用查找的方式进行变量跳转,或者使用外部编辑器编辑**推荐vscode。
五、开发板选择与原理图分享
MCU最小系统电路 四线下载电路 完整开发板原理图和PCB请加全国大学生电子交流QQ群获取:649692007
六、定时器(基于状态机制,下同)
uint32_t CheckTimer(uint32_t Timer)
{
if(BaseTimerCount > Timer){ return(BaseTimerCount - Timer); }
else{ return ~(Timer - BaseTimerCount) + 1; }
}
int main(void)
{
uint32_t timerx_1s;
uint32_t timerx_2s;
uint32_t timerx_3s;
R_TAU0_Channel0_Start();
timerx_1s = BaseTimerCount;
timerx_2s = BaseTimerCount;
timerx_3s = BaseTimerCount;
while(1U)
{
if(CheckTimer(timerx_1s)>1000)
{
timerx_1s = BaseTimerCount;
}
if(CheckTimer(timerx_2s)>2000)
{
timerx_2s = BaseTimerCount;
}
if(CheckTimer(timerx_3s)>3000)
{
timerx_3s = BaseTimerCount;
}
}
}
七、LED流水灯
int main(void)
{
uint32_t timerx_1s;
R_TAU0_Channel0_Start();
timerx_1s = BaseTimerCount;
while(1U)
{
if(CheckTimer(timerx_1s)>1000)
{
timerx_1s = BaseTimerCount;
P1^=0x01;
}
}
}
八、串口初始化
uint8_t Uart0_SendByte(uint8_t u8Data)
{
uint16_t timesout = 0;
STMK0 = 1U;
STIF0 = 0U;
TXD0 = u8Data;
while(STIF0 == 0U)
{
timesout++;
if(timesout>50000){
break;
}
}
STIF0 = 0U;
return (timesout>5000)?1:0;
}
volatile uint8_t Uart0Rx_Buf[128];
typedef enum SAUTASK
{
SauTask_Init = 0,
SauTask_Idle,
SauTask_Rev,
SauTask_NoExBat,
SauTask_Stop,
}SauTaskState_Type;
extern volatile uint16_t g_uart0_rx_count;
SauTaskState_Type SauTaskState0;
void Sau0_Run_Task(void)
{
uint8_t i = 0;
static uint8_t sau_first_flag = 0;
static uint32_t sau_timer = 0;
static uint8_t last_rx_count = 0xFF;
switch(SauTaskState0)
{
case SauTask_Init:
last_rx_count = 0xFF;
R_UART0_Start();
R_UART0_Receive(Uart0Rx_Buf,128);
SauTaskState0 = SauTask_Idle;
break;
case SauTask_Idle:
if(g_uart0_rx_count>1)
{
last_rx_count = (uint8_t)(g_uart0_rx_count&0x0FF);
sau_timer = BaseTimerCount;
SauTaskState0 = SauTask_Rev;
}
break;
case SauTask_Rev:
if(g_uart0_rx_count!=last_rx_count)
{
last_rx_count = (uint8_t)(g_uart0_rx_count&0x0FF);
sau_timer = BaseTimerCount;
}
else
{
if(CheckTimer(sau_timer)>TIME_5MS)
{
for(i=0;i<last_rx_count;i++)
{
Uart0_SendByte(Uart0Rx_Buf[i]);
}
sau_timer = BaseTimerCount;
R_UART0_Receive(Uart0Rx_Buf,128);
SauTaskState0 = SauTask_Idle;
}
}
break;
case SauTask_NoExBat:
R_UART0_Stop();
break;
default:break;
}
}
int main(void)
{
R_TAU0_Channel0_Start();
while(1U)
{
Sau0_Run_Task();
}
}
九、串口printf
#define __out_putchar Uart0_SendByte
#define MAX_NUMBER_BYTES 64
typedef char * va_list;
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) + 6 )
#define va_arg(ap,t) ( *(t *)( ap=ap + _INTSIZEOF(t), ap - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
unsigned char hex_tab[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
static int outc(int c)
{
__out_putchar((unsigned char)c);
return 0;
}
static int outs (const char *s)
{
while (*s != '\0')
__out_putchar(*s++);
return 0;
}
static int out_num(long n, int base,char lead,int maxwidth)
{
unsigned long m=0;
char buf[MAX_NUMBER_BYTES], *s = buf + sizeof(buf);
int count=0,i=0;
*--s = '\0';
if (n < 0){m = -n;}else{m = n;}
do{
*--s = hex_tab[m%base];
count++;
}while ((m /= base) != 0);
if( maxwidth && count < maxwidth){
for (i=maxwidth - count; i; i--)
*--s = lead;
}
if (n < 0)*--s = '-';
return outs(s);
}
static int my_vprintf(const char *fmt, va_list ap)
{
char lead = ' ';
int maxwidth = 0;
for(; *fmt != '\0'; fmt++)
{
if (*fmt != '%') {outc(*fmt);continue;}
lead=' ';maxwidth=0;
fmt++;
if(*fmt == '0'){
lead = '0';fmt++;
}
while(*fmt >= '0' && *fmt <= '9'){
maxwidth *=10;
maxwidth += (*fmt - '0');
fmt++;
}
switch (*fmt) {
case 'd': out_num(va_arg(ap, int),10,lead,maxwidth); break;
case 'o': out_num(va_arg(ap, unsigned int), 8,lead,maxwidth); break;
case 'u': out_num(va_arg(ap, unsigned int), 10,lead,maxwidth); break;
case 'x': out_num(va_arg(ap, unsigned int), 16,lead,maxwidth); break;
case 'c': outc(va_arg(ap,int)); break;
case 's': outs(va_arg(ap, char *)); break;
default: outc(*fmt);break;
}
}
return 0;
}
int printf(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
my_vprintf(fmt, ap);
va_end(ap);
return 0;
}
int my_printf_test(void)
{
printf("全国大学生电子交流群:649692007\n\r") ;
printf("test char =%c,%c\n\r", 'A','a') ;
printf("test decimal number =%d\n\r",12345);
printf("test decimal number =%d\n\r",-12345);
printf("test hex number =0x%x\n\r",0x55aa);
printf("test string =%s\n\r","www.100ask.org");
printf("num=%08d\n\r",12345);
printf("num=%8d\n\r",12345);
printf("num=0x%08x\n\r",0x2345);
printf("num=0x%8x\n\r",0x2345);
printf("num=0x%02x\n\r",0x1);
printf("num=0x%2x\n\r",0x1);
printf("num=%05d\n\r",0x1);
printf("num=%5d\n\r",0x1);
return 0;
}
十、ADC电压采集
十一、ADC+DMA
十二、PWM呼吸灯
十三、IIC驱动EEPROM
十四、RTC实时时钟
十五、LCD控制器
十六、按键
欢迎加入全国大学生电子交流QQ群:649692007,获取完整例程源码(顺便熟悉状态机制的编程方法)
|