利用RA-Eco-RA4M2开发板开发板,做一个未做分压的电压表,量程仅3.3v。

出于学习的目的,尽量实践更多的技术细节,有些功能可能和目标没有必然的联系。
一、FSP Smart Configurator开始配置工程
1、主控及目标工程选择

RA4M2主控为R7FA4M2AD3CFP。
出于习惯,选择生成用于vscode编辑的CMAKE工程
2、RTOS

RTOS不是必须的,但为了验证RTOS的使用,将其选上。
二、RTOS配置
1、New Stack->RTOS

RTOS选择了Heap4算法
2、建立2个Thread

3、Thread属性

修改一下Symbol、Name,其他保持默认
如果这时按“Genterate Project Content”
工程中会生成3个entery文件

由于使用了rtos,hal_entery.c不会在main.c中调用。而另外2个entry会被rtos的task函数调用。我们的程序主要在这两个函数中编写。
三、UART配置
1、New Stack->Connectivity->Uart(r_sci_uart)

2、pins选择


3、中断及优先级选择

4、printf重定向
fsp_err_t err = FSP_SUCCESS;
unsigned char send_buff[100];
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
}
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
return ch;
}
int _write(int fd,char *pBuffer,int size)
{
for(int i=0;i
5、在led_Thread_entry初始化uart
err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(FSP_SUCCESS == err);
printf("hello world\r\n");
为使gcc支持print_float,需要在CMakeLists.txt 增加如下配置:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -u _printf_float --specs=nosys.specs")
使用printf float需要修改HEAP size

完成以上UART配置,就可以用printf打印带小数的电压数值了。
四、ADC配置
1、New Stack->Analog->ADC(r_adc)

2、基本配置

修改了name
3、input&Pins

input选择channel4、内部温度传感器、内部电压参考
引脚选择
4、中断设置

设置中断回调函数名、优先级
5、在led_Thread_entry实现以下程序
ADC初始化
void ADC_Init(void)
{
fsp_err_t err;
err = R_ADC_Open(&g_adc4_ctrl, &g_adc4_cfg);
err = R_ADC_ScanCfg(&g_adc4_ctrl, &g_adc4_channel_cfg);
assert(FSP_SUCCESS == err);
}
ADC回调函数
void adc_callback(adc_callback_args_t * p_args)
{
FSP_PARAMETER_NOT_USED(p_args);
scan_complete_flag = true;
}
获取电压数据
double Read_ADC_Voltage_Value(void)
{
uint16_t adc_data;
double a0;
(void)R_ADC_ScanStart(&g_adc4_ctrl);
while (!scan_complete_flag)
{
;
}
scan_complete_flag = false;
R_ADC_Read(&g_adc4_ctrl, ADC_CHANNEL_4, &adc_data);
a0 = (double)(adc_data*3.3/4095);
return a0;
}
获取内部温度传感器
double Read_ADC_Temperature(void)
{
uint16_t adc_data;
int32_t cal127;
R_ADC_ScanStart(&g_adc4_ctrl);
while (!scan_complete_flag)
{
;
}
scan_complete_flag = false;
R_ADC_Read(&g_adc4_ctrl, ADC_CHANNEL_TEMPERATURE, &adc_data);
adc_info_t adc_info;
(void) R_ADC_InfoGet(&g_adc4_ctrl, &adc_info);
cal127 = (int32_t) adc_info.calibration_data;
float slope = 4.0/1000;
float v1= 3.3 * cal127 / 4096;
float vs = 3.3 * adc_data /4096;
double temperature = (vs - v1) / slope + 127;
return temperature;
}
获取内部参考电压并显示
void read_adc_value(void)
{
uint16_t adc_data;
double a0;
uint8_t buf[30]={0};
R_ADC_ScanStart(&g_adc4_ctrl);
while (!scan_complete_flag)
{
;
}
scan_complete_flag = false;
R_ADC_Read(&g_adc4_ctrl, ADC_CHANNEL_VOLT, &adc_data);
a0 = (double)(adc_data*3.3/4095);
sprintf((char*)buf,"%05.2f",a0);
GUI_WriteASCII_BIG(60,55,buf,VGA_WHITE,VGA_GREEN);
}
6、完整的led_Thread_entry
void led_Thread_entry(void * pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(FSP_SUCCESS == err);
printf("hello world\r\n");
uint8_t buf[30]={0};
ADC_Init();
init_lcd();
clear_screen(VGA_BLACK);
GUI_ShowLogo(0,0,216,176,VGA_RED,VGA_BLACK);
vTaskDelay(2000);
clear_screen(VGA_BLACK);
fillRect(5,5,215,53,VGA_RED);
fillRect(5,55,215,103,VGA_GREEN);
fillRect(5,105,215,153,VGA_BLUE);
fillRect(5,155,215,175,VGA_MAROON);
GUI_Write16CnChar(10,20,(uint8_t*)"电压",VGA_WHITE,VGA_RED);
GUI_Write16CnChar(190,28,(uint8_t*)"V",VGA_WHITE,VGA_RED);
GUI_Write16CnChar(10,70,(uint8_t*)"参考",VGA_WHITE,VGA_GREEN);
GUI_Write16CnChar(190,78,(uint8_t*)"V",VGA_WHITE,VGA_GREEN);
GUI_Write16CnChar(10,120,(uint8_t*)"温度",VGA_WHITE,VGA_BLUE);
GUI_Write16CnChar(190,128,(uint8_t*)"℃",VGA_WHITE,VGA_BLUE);
GUI_Write16CnChar(66,157,(uint8_t*)"RA4M2评测",VGA_WHITE,VGA_MAROON);
while(1)
{
LED1_TOGGLE;
sprintf((char*)buf,"%05.2f", Read_ADC_Voltage_Value());
printf(buf);
GUI_WriteASCII_BIG(60,5,buf,VGA_WHITE,VGA_RED);
read_adc_value();
sprintf((char*)buf,"%05.2f", Read_ADC_Temperature());
GUI_WriteASCII_BIG(60,105,buf,VGA_WHITE,VGA_BLUE);
vTaskDelay(1000);
}
}
五、另一个Thread
主要是验证RTOS,判断外部中断,点亮LED
extern volatile bool key1_sw2_press;
extern volatile bool key2_sw3_press;
e
void key_Thread_entry(void * pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
Key_IRQ_Init();
while(1)
{
if (key1_sw2_press)
{
key1_sw2_press = false;
LED2_TOGGLE;
}
if (key2_sw3_press)
{
key2_sw3_press = false;
LED3_TOGGLE;
}
vTaskDelay(100);
}
}
六、运行




