龙芯1B开发板自检程序
本代码为当时,参加嵌入式系统开发与应用赛项,训练时编写的自检程序,用于将程序烧录后,逐个演示板载模块功能是否正常,快速定位问题。这代码编写的时间为2023
年,好像原代码是参考2023年官方案例来编写的。目前代码版本,和模块应该已经更新,所以参考价值不一定高。还有当时在编写时,是有些坑的,例如LCD方向定义有点问题,好像哪个库代码还少了部分之类的,总之有时候,有些功能给了接口,但是功能没有实装的,不过现在源代码迭代了些,应该修复了不少吧。
- 软件:Embedded IDE for Loongson
- 开发板,如下图
下述为main.c代码,完整项目放在末尾。
#include <stdio.h>#include "ls1b.h"
#include "mips.h"//-------------------------------------------------------------------------------------------------
// BSP
//-------------------------------------------------------------------------------------------------#include "bsp.h"
#include "led_drv.h"
#include "key_drv.h"
#include "beep.h"
#include "uart.h"
#include "lkdGui.h" // 显示库
#include "stdint.h" // 显示相关
#include "ls1x_i2c_bus.h" // i2C总线
#include "i2c/ads1015.h" // ADC芯片
#include "i2c/mcp4725.h" // ADC相关
#include "pwm_ic.h" // PWM相关
#include "bh1750_iic.h" // BH1750
#include "bh1750.h" // BH1750
#include "libc/lwmem.h" // LCD相关
#include "pic_flag.h" // 图片存放
#include "i2c/gt1151.h" // 触摸相关
#include "fan_resistance_control_drv.h" // 风扇控制
#include "lm35_drv.h" // 温度测量
#include "ls1b_gpio.h" // GPIO控制#ifdef BSP_USE_FB
#include "ls1x_fb.h"
#ifdef XPT2046_DRV
char LCD_display_mode[] = LCD_800x480;
#elif defined(GT1151_DRV)
char LCD_display_mode[] = LCD_800x480;
#else
#error "在bsp.h中选择配置 XPT2046_DRV 或者 GT1151_DRV"
"XPT2046_DRV: 用于800*480 横屏的触摸屏."
"GT1151_DRV: 用于480*800 竖屏的触摸屏."
"如果都不选择, 注释掉本 error 信息, 然后自定义: LCD_display_mode[]"
#endif
#endif/**** 辅助程序 ****/
unsigned int TaskTextRoll_Row = 0; // 行索引
unsigned char TaskTextRoll_RowHigh = 35; // 行高度
unsigned char JsMode_Num = 3; // 计数模式的倒计时char textBuf[50]= {0};
// 任务文本滚动
// str:字符串
// mode:模式选择 0.默认显示模式 1.计数等待模式 2.顺序例出文本且间隔比较大
void TaskTextRoll(uint8_t *str ,uint8_t mode)
{uint8_t i;switch(mode){case 0:TaskTextRoll_Row += 1; // 行数递增GuiRowText(30, 10+(TaskTextRoll_RowHigh * TaskTextRoll_Row) ,480, FONT_LEFT,str);printk(str);printk("\r\n");break;case 1:delay_ms(1000);for(i = 0; i < JsMode_Num; i++){sprintf((char *)textBuf,"%d",JsMode_Num-i);GuiRowText(280+(i*50), 10+(TaskTextRoll_RowHigh * TaskTextRoll_Row) ,30, FONT_LEFT,textBuf);printk(textBuf);printk(" ");delay_ms(1000);}printk("\r\n");break;case 2:TaskTextRoll_Row += 1; // 行数递增GuiRowText(60, 30+(TaskTextRoll_RowHigh * TaskTextRoll_Row) ,480, FONT_LEFT,str);printk(str);printk("\r\n");break;default:GuiRowText(30, (TaskTextRoll_RowHigh * TaskTextRoll_Row) ,480, FONT_LEFT,"显示错误!");break;}}unsigned char KEY_keyNum = 0;
unsigned char KEY_ExitKey = 4;
// 按键跳过程序
// 将该函数放置要循环的任务语句中
unsigned char KEY_SKipTask(void)
{KEY_keyNum = KEY_Scan();if(KEY_keyNum == KEY_ExitKey) return 0;return 1;
}//-------------------------------------------------------------------------------------------------
// 主程序
//-------------------------------------------------------------------------------------------------
/***** 任务函数 *****/
//任务1现象--红绿蓝分别保持1秒
void Task1_LED(void)
{//printk("Task1_LED_start\r\n");LED_Init();while(KEY_SKipTask()){LED_RGBDemo();}//printk("Task1_LED_end\r\n");
}//任务2现象-- S1-亮红灯 S2--亮绿灯 S3--亮蓝灯 S4--退出该任务
void Task2_KEY(void)
{unsigned char keyNum = 0;unsigned char status = 0;KEY_Init();//printk("Task2_KEY_start\r\n");while(1){keyNum = KEY_Scan();status = 0;switch ( keyNum ){case 1:LED_On( LED1 );LED_Off( LED2 );LED_Off( LED3 );delay_ms(500);break;case 2:LED_On( LED2 );LED_Off( LED1 );LED_Off( LED3 );delay_ms(500);break;case 3:LED_On( LED3 );LED_Off( LED1 );LED_Off( LED2 );delay_ms(500);break;case 4:status = 1;break;default:LED_Off( LED1 );LED_Off( LED2 );LED_Off( LED3 );break;}if(status == 1) break;}//printk("Task2_KEY_end\r\n");
}//任务3现象--蜂鸣器响起
void Task3_BEEP(void)
{//printk("Task3_BEEP_start\r\n");BEEP_Init();BEEP_On();delay_ms(500);BEEP_Off();delay_ms(500);BEEP_On();delay_ms(500);BEEP_Off();delay_ms(500);BEEP_On();delay_ms(500);BEEP_Off();delay_ms(500);//printk("Task3_BEEP_end\r\n");
}//任务4现象--UART交互(波特率115200)
void Task4_UART(void)
{//printk("Task4_UART_start\r\n");UART5_Config_Init();LED_Off(LED1);//串口控制函数while(UART5_Test()){if(!(KEY_SKipTask())) break;}//printk("Task4_UART_end\r\n");
}extern float temp;
double lm35_temp_data;
char str[100];
//任务5现象--风扇与加热
void Task5_FAN_HOT(void)
{unsigned char i = 0;unsigned int i_5S = 0;unsigned char Tempfirst = 0; // 记录初始温度unsigned char TempEnd = 0; // 记录最后温度fan_resistance_io_Config();gpio_write(38,1);//加热电阻打开gpio_write(36,1);//风扇开关打开Fan_Control(100);//风扇控制PWM最大ls1x_i2c_initialize(busI2C0);ls1x_ads1015_ioctl(busI2C0,IOCTL_ADS1015_DISP_CONFIG_REG,NULL);GuiRowText(50, 550,400, FONT_MID, "加热30S电阻测温度");//GuiRowText(50, 590,480, FONT_LEFT, "加热模式");//GuiRowText(50, 590,480, FONT_LEFT, " ");// 进入时测量(5S)GuiRowText(50, 590,480, FONT_LEFT, "测量模式: 进行中");GuiRowText(50, 630,400, FONT_LEFT, "当前温度:");while(i_5S < 25){lm35_get_temp();GuiRowText(220, 630,480, FONT_LEFT, " ");sprintf(str,"%.01f℃",temp);GuiRowText(220, 630,400, FONT_LEFT, str);delay_ms(200);i_5S++;}Tempfirst = temp;// 加热30SGuiRowText(50, 590,480, FONT_LEFT, "加热模式: ");for(i=0;i<30;i++){GuiRowText(220, 590,480, FONT_LEFT, " ");sprintf(str,"%d S",30-i);GuiRowText(220, 590,480, FONT_LEFT, str);delay_ms(1000);}gpio_write(38,0);//加热电阻关闭gpio_write(36,0);//风扇开关关闭GuiRowText(50, 590,480, FONT_LEFT, " ");GuiRowText(50, 590,480, FONT_LEFT, "测量模式: 进行中");GuiRowText(50, 630,400, FONT_LEFT, "当前温度:");while(KEY_SKipTask()){lm35_get_temp();GuiRowText(220, 630,480, FONT_LEFT, " ");sprintf(str,"%.01f℃",temp);GuiRowText(220, 630,400, FONT_LEFT, str);delay_ms(200);TempEnd = temp;GuiRowText(220, 670,480, FONT_LEFT, " ");sprintf(str,"初始温度:%d",Tempfirst);GuiRowText(50, 670,400, FONT_LEFT, str);GuiRowText(220, 710,480, FONT_LEFT, " ");sprintf(str,"温度差值:%d",(TempEnd-Tempfirst)>0?TempEnd-Tempfirst:(TempEnd-Tempfirst)*(-1));GuiRowText(50, 710,400, FONT_LEFT, str);}// 清除fb_fillrect(0, 0, 350, 480, cidxBLACK);
}//任务6现象--语音模块交互
void Task6_VOICE(void)
{//printk("Task6_VOICE_start\r\n");//printk("Task6_VOICE_end\r\n");
}//任务数码管验证
void Task7_SMG(void)
{//printk("Task7_SMG_start\r\n");int num;SMG_Init();while(KEY_SKipTask()){num = 9999;while(1){SMG_SeleNumDyn(num,1000);num -= 1111;if(num == 0) break;}}//printk("Task7_SMG_end\r\n");
}char tbuf1[50]= {0},tbuf2[50]= {0},tbuf3[50]= {0},tbuf4[50]= {0},sbuf1[50]= {0},sbuf2[50]= {0},sbuf3[50]= {0},sbuf4[50]= {0},rt;
unsigned short dac=0, adc1=0, adc2=0, adc3=0, adc4=0;
float out_v,in_v1,in_v2,in_v3,in_v4;void Task8_I2C_ADC(void)
{unsigned char quitNum = 0;unsigned int RowAdjust = 550; // Y 轴显示高度补偿ls1x_ads1015_ioctl(busI2C0,IOCTL_ADS1015_DISP_CONFIG_REG,NULL);while(KEY_SKipTask()){adc1 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_0);adc2 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_1);adc3 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_2);adc4 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_3);in_v1 = 4.096*2*adc1/4096;//采集电压的转换公式in_v2 = 4.096*2*adc2/4096;//采集电压的转换公式in_v3 = 4.096*2*adc3/4096;//采集电压的转换公式in_v4 = 4.096*2*adc4/4096;//采集电压的转换公式sprintf((char *)sbuf1,"CH 1 = %f V",in_v1);sprintf((char *)sbuf2,"CH 2 = %f V",in_v2);sprintf((char *)sbuf3,"CH 3 = %f V",in_v3);sprintf((char *)sbuf4,"CH 4 = %f V",in_v4);GuiRowText(30, 30+RowAdjust,400, FONT_LEFT, "ADS1015 ADC GET");GuiRowText(30, 60+RowAdjust,400, FONT_LEFT,sbuf1);GuiRowText(30, 90+RowAdjust,400, FONT_LEFT,sbuf2);GuiRowText(30, 120+RowAdjust,400, FONT_LEFT,sbuf3);GuiRowText(30, 150+RowAdjust,400, FONT_LEFT,sbuf4);//fb_textout(10, 60, "ADS1015 ADC GET");delay_ms(500);quitNum ++;//if(quitNum>10) break;}fb_fillrect(0, 0, 350, 480, cidxBLACK);}char data[20];
unsigned int frequency = 5000;
unsigned int x_i=0; //X轴绘图前进
void Task9_PWM(void)
{unsigned int i = 0;unsigned char isDown = 0;GuiRowText(50, 550,400, FONT_LEFT, "PWM输出");GuiRowText(50, 580,400, FONT_LEFT, "PWM输出占空比为:");// 容器化(统一宽高)// xy轴画线GuiRLine(50,650,750,cidxRED);GuiHLine(50,750,400,cidxRED);//Set_PWM(500); // 20KMz// 触顶低反弹for(i = 0; isDown?i>=0:i<101 ; isDown?i--:i++){sprintf(data,"%d ",i);GuiRowText(320, 580,400, FONT_LEFT, data);x_i++; // 递进数GuiPoint(50+x_i,750-i,cidxGREEN); //绘制波形// 设置PWM函数(我也不知道为啥这么设,只是验证后现象没问题)// 数值越大越慢Set_PWM(i*50);delay_ms(100);// 触顶低反弹逻辑if(i == 0){i=1 ;isDown = 0;}else if(i == 100){i=99 ;isDown = 1;}// 退出逻辑if(50 + x_i > 400){break;}}while(KEY_SKipTask());fb_fillrect(0, 0, 350, 480, cidxBLACK);
}unsigned int task10_ContY = 550;
void Task10_BH1750(void)
{unsigned char buf[20] = {0};unsigned int lx = 0;BH1750_Init(); //光照强度传感器初始化GuiRowText(50, 30+task10_ContY, 400, FONT_LEFT, "BH1750光照度传感器测量");GuiRowText(50, 70+task10_ContY, 400, FONT_LEFT, "光照传感器");GuiRowText(50, 110+task10_ContY, 400, FONT_LEFT, "当前光照强度:");while(KEY_SKipTask()){// 循环检测部分sprintf((char *)buf,"%d lux", BH1750_reData());GuiRowText(280, 110+task10_ContY, 400, FONT_LEFT, buf);}fb_fillrect(0, 0, 350, 480, cidxBLACK);
}void Task11_LCD(void)
{//初始化内存堆//lwmem_initialize(0);delay_ms(500);fb_cons_clear();//清屏//while(KEY_SKipTask())//{// 颜色充填演示fb_fillrect(0, 0, 800, 480, cidxRED);delay_ms(1500);fb_fillrect(0, 0, 800, 480, cidxYELLOW);delay_ms(1500);fb_fillrect(0, 0, 800, 480, cidxBLUE);delay_ms(1500);fb_fillrect(0, 0, 800, 480, cidxBLACK);delay_ms(1500);// 图片演示display_pic(50,50,400,400,gImage_img); //显示图片delay_ms(1500);//}
}void Task12_Toush(void)
{//GT1151_Init();//GT1151_Test();
}// 自检任务演示--综合
void TaskDemo_AND(void)
{// 综合演示模式while(1){GuiRowText(0, 0,480, FONT_MID,"龙芯1B自检程序");TaskTextRoll("Task1_LED",0);TaskTextRoll("0",1);Task1_LED();delay_ms(1000);TaskTextRoll("Task2_KEY",0);TaskTextRoll("0",1);Task2_KEY();delay_ms(1000);TaskTextRoll("Task3_BEEP",0);TaskTextRoll("0",1);Task3_BEEP();delay_ms(1000);TaskTextRoll("Task4_UART",0);TaskTextRoll("0",1);Task4_UART();delay_ms(1000);TaskTextRoll("Task5_FAN_HOT",0);TaskTextRoll("0",1);Task5_FAN_HOT();delay_ms(1000);TaskTextRoll("Task6_VOICE",0);TaskTextRoll("0",1);Task6_VOICE();delay_ms(1000);TaskTextRoll("Task7_SMG",0);TaskTextRoll("0",1);Task7_SMG();delay_ms(1000);TaskTextRoll("Task8_I2C_ADC",0);TaskTextRoll("0",1);Task8_I2C_ADC();delay_ms(1000);TaskTextRoll("Task9_PWM",0);TaskTextRoll("0",1);Task9_PWM();delay_ms(1000);TaskTextRoll("Task10_BH1750",0);TaskTextRoll("0",1);Task10_BH1750();delay_ms(1000);TaskTextRoll("Task11_LCD",0);TaskTextRoll("0",1);Task11_LCD();delay_ms(1000);//TaskTextRoll("Task12_Toush",0);//TaskTextRoll("0",1);//Task12_Toush();//delay_ms(1000);break;}
}// 自检任务演示--单独
void TaskDemo_ONE(void)
{int taskNum = 1; // 选择的任务数(1~11)unsigned char keyNum = 0; // 1.- 2.确定 3.+ 4.退出// 清光标fb_fillrect(0, 0, 800, 60, cidxBLACK);// 任务列表显示TaskTextRoll("Task1_LED",2);TaskTextRoll("Task2_KEY",2);TaskTextRoll("Task3_BEEP",2);TaskTextRoll("Task4_UART",2);TaskTextRoll("Task5_FAN_HOT",2);TaskTextRoll("Task6_VOICE",2);TaskTextRoll("Task7_SMG",2);TaskTextRoll("Task8_I2C_ADC",2);TaskTextRoll("Task9_PWM",2);TaskTextRoll("Task10_BH1750",2);TaskTextRoll("Task11_LCD",2);char* data[10];// 单独演示模式while(1){sprintf(data,"%d ",taskNum);GuiRowText(0, 0 ,40, FONT_LEFT,data);keyNum = KEY_Scan();switch(keyNum){case 1: // 减if(taskNum-1>0) {taskNum-=1;// 清光标//fb_fillrect(0, 0, 800, 60, cidxBLACK);// 光标(任务数选择)//GuiFillRect(0,0+20*(taskNum),20,20+20*(taskNum),cidxWHITE);}break;case 4: // 确定switch(taskNum){case 1:Task1_LED();break;case 2:Task2_KEY();break;case 3:Task3_BEEP();break;case 4:Task4_UART();break;case 5:Task5_FAN_HOT();break;case 6:Task6_VOICE();break;case 7:Task7_SMG();break;case 8:Task8_I2C_ADC();break;case 9:Task9_PWM();break;case 10:Task10_BH1750();break;case 11:Task11_LCD();break;}break;case 3: // 加if(taskNum+1<12){taskNum+=1;// 清光标fb_fillrect(0, 0, 800, 60, cidxBLACK);// 光标(任务数选择)//GuiFillRect(0,0+20*(taskNum),20,20+30*(taskNum),cidxWHITE);}break;}}
}int DemoMode = 1; // 演示模式 1.综合演示模式 2.单独演示模式
// 自检任务
void TaskDemo(void)
{unsigned char keyNum = 0; // 健值// 屏幕显示初始化fb_open(); //打开LCD显示delay_ms(500);fb_cons_clear(); //清屏defaultFontInit(); /* 字库初始化 */GuiUpdateDisplayAll(); /* 更新屏幕-清屏 */// 开机介绍GuiRowText(0, 240,480, FONT_MID,"龙芯1B自检程序介绍");GuiRowText(0, 290,480, FONT_LEFT," 任务会按顺序依次演示,大多");GuiRowText(0, 330,480, FONT_LEFT,"数任务是存在循环演示,可以按S4");GuiRowText(0, 370,480, FONT_LEFT,"按键跳转到下个任务。现在就可以");GuiRowText(0, 410,480, FONT_LEFT,"按下S4按键开始自检程序。");while(KEY_SKipTask());fb_fillrect(0, 0, 800, 480, cidxBLACK);delay_ms(1000);// 演示模式选择KEY_Init();GuiRowText(0, 340,480, FONT_MID,"->综合演示模式");GuiRowText(0, 400,480, FONT_MID," 单独演示模式");while(KEY_SKipTask()){keyNum = KEY_Scan();switch(keyNum){case 1: // 1.综合演示模式 DemoMode = 1;GuiRowText(0, 340,480, FONT_MID,"->综合演示模式");GuiRowText(0, 400,480, FONT_MID," 单独演示模式");break;case 2: // 2.单独演示模式DemoMode = 2;GuiRowText(0, 340,480, FONT_MID," 综合演示模式");GuiRowText(0, 400,480, FONT_MID,"->单独演示模式");break;}}fb_fillrect(0, 0, 800, 480, cidxBLACK);// 进入模式switch(DemoMode){case 1:TaskDemo_AND();break;case 2:TaskDemo_ONE();break;}}int main(void)
{printk("\r\nmain() function.\r\n");ls1x_drv_init(); /* Initialize device drivers */install_3th_libraries(); /* Install 3th libraies */// 屏幕显示初始化fb_open(); //打开LCD显示delay_ms(500);fb_cons_clear(); //清屏defaultFontInit(); /* 字库初始化 */GuiUpdateDisplayAll(); /* 更新屏幕-清屏 */KEY_Init();// 自检程序TaskDemo();/** 裸机主循环*/for (;;){//unsigned int tickcount = get_clock_ticks();//printk("tick count = %i\r\n", tickcount);//BH1750_Test();//delay_ms(500);}/** Never goto here!*/return 0;
}/** @@ End*/
完整工程链接,希望能帮助到大家!
龙芯1B开发板自检程序
链接:https://pan.baidu.com/s/1dyx5YroQxsvu4-pEHARj3Q 提取码:di6t