代码资源下载:https://download.csdn.net/download/BaoTTing/58444918
一、开发环境介绍
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
六、定时器(基于状态机制,下同)
//根据BaseTimerCount计算差值函数
uint32_t CheckTimer(uint32_t Timer)
{
if(BaseTimerCount > Timer){ return(BaseTimerCount - Timer); }
else{ return ~(Timer - BaseTimerCount) + 1; }
}
//示例函数:实现1s、2s、3s周期的定时
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;
//.......... <---1s周期任务
}
if(CheckTimer(timerx_2s)>2000)
{
timerx_2s = BaseTimerCount;
//.......... <---2s周期任务
}
if(CheckTimer(timerx_3s)>3000)
{
timerx_3s = BaseTimerCount;
//.......... <---3s周期任务
}
}
}
七、LED流水灯
//示例函数:实现1s、2s、3s周期的定时
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; //LED 1s翻转一次
}
}
}
八、串口初始化
/**
* @brief : Uart0字节发送函数
* @param :
* @u8Data: 要发送的数据
* @note : 非中断方式
* @retval: 是否超时
*/
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];
/**
* @brief : Uart0任务函数
* @param : 无
* @note : 收到什么数据,打印什么数据
* @retval: 无
*/
typedef enum SAUTASK //TaskState-Enum
{
SauTask_Init = 0, //Init----Mode
SauTask_Idle, //Idle----Mode
SauTask_Rev, //Receive-Mode
SauTask_NoExBat, //NoExBat-Mode
SauTask_Stop, //Stop----Mode
}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
/*注意:由于单片机是16位的,遵循双字节对齐,所以数字项最大值为65535,超过的部分将被强制转化*/
#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 ) //v = 第一个传入参数*,ap = 第二个传入参数的地址
#define va_arg(ap,t) ( *(t *)( ap=ap + _INTSIZEOF(t), ap - _INTSIZEOF(t)) ) //返回当前参数地址,ap指向下一个参数
#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;}//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;}//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); /*注:max=65535*/
printf("test decimal number =%d\n\r",-12345); /*注:max=65535*/
printf("test hex number =0x%x\n\r",0x55aa); /*注:max=65535*/
printf("test string =%s\n\r","www.100ask.org");/*注:max=65535*/
printf("num=%08d\n\r",12345); /*注:max=65535*/
printf("num=%8d\n\r",12345); /*注:max=65535*/
printf("num=0x%08x\n\r",0x2345); /*注:max=65535*/
printf("num=0x%8x\n\r",0x2345); /*注:max=65535*/
printf("num=0x%02x\n\r",0x1); /*注:max=65535*/
printf("num=0x%2x\n\r",0x1); /*注:max=65535*/
printf("num=%05d\n\r",0x1); /*注:max=65535*/
printf("num=%5d\n\r",0x1); /*注:max=65535*/
return 0;
}
十、ADC电压采集
十一、ADC+DMA
十二、PWM呼吸灯
十三、IIC驱动EEPROM
十四、RTC实时时钟
十五、LCD控制器
十六、按键
欢迎加入全国大学生电子交流QQ群:649692007