使用的是20pin的 LSSOP封装的,如果没有做PCB板子的需要买一个芯片烧录底座,这里就遇到了第一个坑 买烧录器的时候一定要看清楚芯片封装规格 LSSOP(0.65 mm pitch)
直接上图
三路的温度探头、一路的电流检测的霍尔传感器,还有两个LED灯用来输出状态
烧录器的连接呢也有很多的坑
使用的是EZ-Cube仿真器
VCC---------板子VDD
GND---------板子VSS
FLMD0------板子TOOL0
RESETOUT----板子RESET
仿真器链接的时候板子是不工作的,因为会把RESET引脚拉高导致整个板子复位状态
如果你需要使用仿真器供电工作的话,可以把除了VCC和GND的引脚拔掉
使用的是CubeSuit+ 也就是CS+ 瑞萨的IDE
非常棒的代码生成功能,个人觉得比STM32CubeMX生成的代码还简洁,几乎都是对寄存器的直接操作,还有用户接口层方便使用开发
这个直接先Fix setting就行
我这里使用的是内部时钟,一共就一两块的单片机实现简单的功能没必要搞个外部晶振。
其他的Port Timer这些就按照自己的实际使用情况来设置。
注意一点这里,IDE是默认配置打开了看门狗的,但是这个看门狗好像不是那么好用,不知道是因为我使用内部时钟喂狗不准确还是怎么了,反正就是莫名其妙的复位
不建议打开
总的配置就差不多这样
void R_Systeminit(void)
{
PIOR = 0x00U;
R_CGC_Get_ResetSource();
R_CGC_Create();
R_PORT_Create();
R_SAU0_Create();
R_ADC_Create();
R_TAU0_Create();
IAWCTL = 0x00U;
}
当你配置好了你所需要的板上资源生成代码以后,在r_systemint.c这个文件将你所配置的东西都调用,打开对应寄存器配置对应寄存器都在这个函数里面,这个是自动生成的不用我们去写的哈
void R_MAIN_UserInit(void)
{
/* Start user code. Do not edit comment generated here */
R_UART0_Start();
R_ADC_Set_OperationOn();
/* End user code. Do not edit comment generated here */
}
这个函数也是自动生成的,这个就是用户层的初始化了,比如我使用到了串口0,我就需要在这里面 R_UART0_Start();将串口打开, R_ADC_Set_OperationOn();开机AD转换。
瑞萨里面生成的代码是没有像STM32CubeMX一样有HAL库的 HAL_Delay可以直接使用的
所以需要自己写一个延时函数,为了使用高精度定时我就用定时器来做延时了
配置好一个一毫秒的定时器,非常简单的实现高精度延时
uint16_t delayms = 0; //放在定时中断中使用
void delay(uint16_t ms)
{
R_TAU0_Channel0_Start();
while(delayms < ms)
{
;
}
delayms = 0;
R_TAU0_Channel0_Stop();
}
获取AD采样值函数,这里要注意 这个单片机是16位的单片机,所以只能支持10位采样精度。
uint16_t ADValue;
uint16_t Get_ADC_VA(uint8_t CH)//获取采样值
{
switch (CH)
{
case 0:
ADS &= 0x00;
ADS = 0;
R_ADC_Start();
while (!ADIF);
ADIF = 0U;
R_ADC_Get_Result(&ADValue);
break;
case 1:
ADS &= 0x00;
ADS = 1;
R_ADC_Start();
while (!ADIF);
ADIF = 0U;
R_ADC_Get_Result(&ADValue);
break;
case 2:
ADS &= 0x00;
ADS = 2;
R_ADC_Start();
while (!ADIF);
ADIF = 0U;
R_ADC_Get_Result(&ADValue);
break;
case 3:
ADS &= 0x00;
ADS = 3;
R_ADC_Start();
while (!ADIF);
ADIF = 0U;
R_ADC_Get_Result(&ADValue);
break;
default:
break;
}
return ADValue;
}
uint16_t AD_VAL_ARG(uint8_t CH,uint8_t times)//简单的均值滤波
{
uint8_t i;
uint16_t count=0;
if(times>60)times=60;
for(i=0;i<times;i++)
{
count += Get_ADC_VA(CH);
delay(1);
}
return count/times;
}
在选取通道的时候只需要对ADS寄存器进行复制就行 我这里先清空再赋值。ADIF是采样完成的一个标志寄存器,确保每次采样完成。然后直接调用 R_ADC_Get_Result(&ADValue);就可以读取到采样值了,我这里方便调试实时查看 我就定义了全局变量,因为单片机空间不大很容易出现内存溢出,这里不建议这么做。
void main(void)
{
R_MAIN_UserInit();
/* Start user code. Do not edit comment generated here */
while (1U)
{
num[0] = AD_VAL_ARG(0,20);
temp[0] = num_to_temperature(num[0]);
num[1] = AD_VAL_ARG(1,20);
temp[1] = num_to_temperature(num[1]);
num[2] = AD_VAL_ARG(2,20);
temp[2] = num_to_temperature(num[2]);
num[3] = AD_VAL_ARG(3,50);
IA =(float)num[3]*(5.0/1024) -0.02;
IA1 = ((IA - 2.51)/0.022)/3.0 +1;
// numtobits[0] =(uint8_t)(num[0]>>8);
// numtobits[1] = (uint8_t)num[0];
// R_UART0_Send(numtobits, 2);
if(IA1>0.5)
{
if(temp[0]<40&&temp[1]<40&&temp[2]<40)
{
SWTICH_LOW;
}else SWTICH_HIGH;
}else {
SWTICH_HIGH;
}
//SINGLE_LOW;
delay(100);
//SINGLE_HIGH;
// delay(100);
}
/* End user code. Do not edit comment generated here */
}
通过一个简单的查表法计算温度,空间换时间
uint16_t NTCTAB[151] ={
0x69,0x6E,0x73,0x79,0x7F,0x85,0x8B,0x91,0x98,0x9E,0xA5,0xAC,0xB3,
0xBB,0xC3,0xCA,0xD3,0xDB,0xE3,0xEC,0xF5,0xFE,0x107,0x111,0x11B,
0x125,0x12F,0x139,0x143,0x14E,0x158,0x163,0x16E,0x179,0x184,0x18F,
0x19A,0x1A6,0x1B1,0x1BC,0x1C7,0x1D3,0x1DE,0x1E9,0x1F4,0x200,0x20B,0x216,0x221,
0x22C,0x236,0x241,0x24C,0x256,0x260,0x26B,0x275,0x27F,0x288,0x292,0x29C,
0x2A5,0x2AE,0x2B7,0x2C0,0x2C8,0x2D1,0x2D9,0x2E1,0x2E9,0x2F1,0x2F8,0x300,0x307,
0x30E,0x315,0x31C,0x322,0x328,0x32F,0x335,0x33A,0x340,0x346,0x34B,0x350,0x355,
0x35A,0x35F,0x364,0x368,0x36C,0x371,0x375,0x379,0x37D,0x380,0x384,0x388,0x38B,
0x38E,0x392,0x395,0x398,0x39B,0x39D,0x3A0,0x3A3,0x3A5,0x3A8,0x3AA,0x3AD,0x3AF,
0x3B1,0x3B3,0x3B5,0x3B7,0x3B9,0x3BB,0x3BD,0x3BF,0x3C0,0x3C2,0x3C4,0x3C5,0x3C7,
0x3C8,0x3CA,0x3CB,0x3CD,0x3CE,0x3CF,0x3D1,0x3D2,0x3D3,0x3D4,0x3D5,0x3D6,0x3D8,
0x3D9,0x3DA,0x3DB,0x3DC,0x3DD,0x3DE,0x3DE,0x3DF,0x3E0,0x3E1,0x3E2,0x3E2
};
//二分查表函数
uint8_t look_up_table(uint16_t *a,uint16_t ArrayLong,uint16_t data)
{
uint16_t begin,end,middle ;
uint8_t i ;
begin = 0 ;
end = ArrayLong-1 ;
i = 0 ;
if(data >= a[end]) return end ;
else if(data <= a[begin]) return begin ;
while(begin < end)
{
middle = (begin+end)/2 ;
if(data == a[middle] ) break ;
if(data < a[middle] && data > a[middle-1]) break ;
if(data < a[middle]) end = middle ;
else begin = middle ;
if(i++ > ArrayLong) break ;
}
if(begin > end ) return 0 ;
return middle ;
}
//输入表的序号值,得到温度值
float num_to_temperature(uint16_t data)
{
uint8_t num = look_up_table(NTCTAB,151,data);
float data1;
float temp;
data1 = 1*num-20;
//线性取值 扩大一百倍提高精度
temp = ((float)((data-NTCTAB[num-1])*100/(NTCTAB[num]-NTCTAB[num-1])));
data1 = ((float)data1*100 - temp)/100;
return data1;
}
有些人可能不知道这个表怎么算,百度一下很多的。