这个模块主要提供对外部设备的控制。这里是电机设备。
电机设备和MCU的通信,通过UART完成。
对这个控制模块的封装,一方面是数据,一方面是操作集。
这里关注几个关键点。
先来看数据的封装

class MotorMcu
{
public:struct UartLiteDev* uart_;SystemManager* sys_;...
};

首先,定义索引类的成员变量。
这里面,由于需要使用UART进行操作,所以需要关联一个UART结构体对象,这里没有使用内嵌方式,因为UART是整板的资源,所以使用了索引关联的方式。
这里,由于MotorMCU的对象,是system manager对象的一个成员对象,而且system manager具有最大化的索引范围,所以,这里以索引关联的方式,关联了一个上级system manager对象,形成了源端引用。

然后,定义复杂结构的成员变量,

class MotorMcu
{
public:struct MCU2FPGACommand mcu_cmd_;...
};

这里面,内嵌了一个MCU2FPGACommand结构体。这个结构体将命令块封装成结构体。配套的,需要为这个结构体设计相应的操作集。

struct MCU2FPGACommand
{struct MCU80msCommand mcu80ms_cmd;struct MCUTestCommand mcutest_cmd;struct MCUIrisCommand mcuiris_cmd;
};void mcu2fpga_cmd_init(struct MCU2FPGACommand* cmd);
void mcu2fpga_cmd_parse(struct MCU2FPGACommand* mcu_cmd);
void mcu2fpga_cmd_demux(struct RingBuffer* ring, struct MCU2FPGACommand* mcu_cmd);

这里面又是由三个结构体对象构成。分别定义为

struct MCU80msCommand
{int fresh;u8 data[13];int action;u16 zoom_motor_value;u16 focus_motor_value;u8 zoom_limit;u8 focus_limit;u8 optics_fog_close_limit;u8 optics_fog_open_limit;
};void mcu80ms_cmd_parse(struct MCU80msCommand* mcu80ms_cmd);struct MCUTestCommand
{int fresh;u8 data[10];int action;u8 filter_ok;u8 iris_ok;u8 zoom_ok;u8 focus_ok;
};void mcutest_cmd_parse(struct MCUTestCommand* mcutest_cmd);struct MCUIrisCommand
{int fresh;u8 data[10];int action;u8 iris_limit_mode;
};void mcuiris_cmd_parse(struct MCUIrisCommand* mcuiris_cmd);

另一个需要通信的命令块,也要封装成结构体,及其对应的操作集,

struct FPGA2MCUCommand
{u8 data[19];int len;
};void fpga2mcu_cmd_init(struct FPGA2MCUCommand* cmd);
void fpga2mcu_set_zoom_field(struct FPGA2MCUCommand* cmd, u8 zoom_mode, u8 zoom_speed);
void fpga2mcu_set_focus_field(struct FPGA2MCUCommand* cmd, u8 focus_mode, u8 focus_speed);
void fpga2mcu_set_filter_field(struct FPGA2MCUCommand* cmd, u8 filter_mode, u8 filter_speed);
void fpga2mcu_set_fov_value(struct FPGA2MCUCommand* cmd, u16 fov_value);
void fpga2mcu_set_focus_value(struct FPGA2MCUCommand* cmd, u16 focus_value);
void fpga2mcu_set_iris_field(struct FPGA2MCUCommand* cmd, u8 iris_mode);
void fpga2mcu_cmd_calc_crc(struct FPGA2MCUCommand* cmd);

定义完了命令块,之后需要定义常量参数,
在C语言中,通常使用宏来定义常量,
在C++中,可以用const的方式来定义,这样封装性和可读性更好,说明这些常量是隶属于某个类的。如果用宏来定义,则是属于全局的。这样,不可避免的需要定义超长的名字,以避免和其他位置的同名常量发生命名冲突。

class MotorMcu
{
public:...//固定参数const float max_optics_focus = 275;const float min_optics_focus = 27.5;const float max_optics_fov = 42;const float min_optics_fov = 4.2;const u32 min_focus_value = 30000;const u32 max_focus_value = 60000;const u32 min_zoom_value = 3000;//3000const u32 max_zoom_value = 30000;//30000...
};

定义完了常量后,需要定义特定用途的基本类型成员变量(非结构体对象)。

class MotorMcu
{
public:...//mcu反馈u16 zoom_motor_value_;//0.1mmu16 focus_motor_value_;//16384~65536u8 zoom_limit_;//变倍到达指定位置u8 focus_limit_;//调焦到达指定位置u8 optics_fog_close_limit_;//光学透雾关到位u8 optics_fog_open_limit_;//光学透雾开到位u8 focus_direct_mode_;u8 filter_ok_;u8 iris_ok_;u8 zoom_ok_;u8 focus_ok_;u8 iris_limit_mode_;

封装好了数据,就要封装相关的操作集。
+++++++++++++++++++++++++++++++++++++++++++++++++++
1)构建函数,

MotorMcu::MotorMcu(struct UartLiteDev* uart, SystemManager* sys) : uart_(uart), sys_(sys), focus_direct_mode_(0)
{mcu2fpga_cmd_init(&mcu_cmd_);
}

2)SET系列

void MotorMcu::set_zoom_up(int speed)
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_zoom_field(&cmd, 1, (u8)speed);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_zoom_down(int speed)
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_zoom_field(&cmd, 2, (u8)speed);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_zoom_value(int speed, int value)
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_zoom_field(&cmd, 3, (u8)speed);fpga2mcu_set_fov_value(&cmd, (u16)value);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_focus_far(int speed)
{plog("set_focus_far: %d\r\n", speed);u8 focus_mode = (focus_direct_mode_ == 0) ? 1 : 2;struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_focus_field(&cmd, focus_mode, (u8)speed);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_focus_near(int speed)
{plog("set_focus_near: %d\r\n", speed);u8 focus_mode = (focus_direct_mode_ != 0) ? 1 : 2;struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_focus_field(&cmd, focus_mode, (u8)speed);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_focus_value(int speed, int value)
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_focus_field(&cmd, 3, (u8)speed);fpga2mcu_set_focus_value(&cmd, value);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_filter_light(int speed)
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_filter_field(&cmd, 1, (u8)speed);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_filter_ir(int speed)
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_filter_field(&cmd, 2, (u8)speed);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_motor_stop()
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}void MotorMcu::set_motor_selftest()
{struct FPGA2MCUCommand cmd;fpga2mcu_cmd_init(&cmd);fpga2mcu_set_iris_field(&cmd, 4);fpga2mcu_cmd_calc_crc(&cmd);uart_lite_send(uart_, cmd.data, cmd.len);
}

可以看出,这几个函数的作用,就是填充命令块,然后通过串口将命令块发送出去。

3)GET系列

u32 MotorMcu::get_optics_focus() {return zoom_motor_value_;}int MotorMcu::get_optics_focus_state() {u32 now_focus = zoom_motor_value_;u32 almost_min_focus = min_zoom_value * 110 / 100;u32 almost_max_focus = max_zoom_value * 90 / 100;if (now_focus < almost_min_focus) {return 0;} else if (now_focus < almost_max_focus) {return 1;} else {return 2;}
}

可以看出,这几个函数的作用,就是获取成员变量值,或者根据成员变量值经过计算后,返回相应的状态值。

4)ACTION系列

void MotorMcu::mcu2fpga_cmd_action(struct MCU2FPGACommand* mcu_cmd)
{struct MCU80msCommand* mcu80ms_cmd = &mcu_cmd->mcu80ms_cmd;struct MCUTestCommand* mcutest_cmd = &mcu_cmd->mcutest_cmd;struct MCUIrisCommand* mcuiris_cmd = &mcu_cmd->mcuiris_cmd;mcu80ms_cmd_action(mcu80ms_cmd);mcutest_cmd_action(mcutest_cmd);mcuiris_cmd_action(mcuiris_cmd);
}void MotorMcu::mcu80ms_cmd_action(struct MCU80msCommand* mcu80ms_cmd)
{if (!mcu80ms_cmd->action)return;mcu80ms_cmd->action = 0;zoom_motor_value_ = mcu80ms_cmd->zoom_motor_value;focus_motor_value_ = mcu80ms_cmd->focus_motor_value;zoom_limit_ = mcu80ms_cmd->zoom_limit;focus_limit_ = mcu80ms_cmd->focus_limit;optics_fog_close_limit_ = mcu80ms_cmd->optics_fog_close_limit;optics_fog_open_limit_ = mcu80ms_cmd->optics_fog_open_limit;
}void MotorMcu::mcutest_cmd_action(struct MCUTestCommand* mcutest_cmd)
{if (!mcutest_cmd->action)return;mcutest_cmd->action = 0;filter_ok_ = mcutest_cmd->filter_ok;iris_ok_ = mcutest_cmd->iris_ok;zoom_ok_ = mcutest_cmd->zoom_ok;focus_ok_ = mcutest_cmd->focus_ok;
}void MotorMcu::mcuiris_cmd_action(struct MCUIrisCommand* mcuiris_cmd)
{if (!mcuiris_cmd->action)return;mcuiris_cmd->action = 0;iris_limit_mode_ = mcuiris_cmd->iris_limit_mode;
}

可以看出,这几个函数的作用,就是从命令块中取出数据,并赋值给对应的成员变量。

5)DEMUX,功能级函数

void MotorMcu::demux(struct RingBuffer* ring, struct MCU2FPGACommand* mcu_cmd)
{unsigned char temp;unsigned char buff[35];struct MCU80msCommand* mcu80ms_cmd = &mcu_cmd->mcu80ms_cmd;struct MCUTestCommand* mcutest_cmd = &mcu_cmd->mcutest_cmd;struct MCUIrisCommand* mcuiris_cmd = &mcu_cmd->mcuiris_cmd;unsigned char* pdata = (unsigned char*)&buff[0];int timeout = 1000;u32 start_time = sys_->get_timestamp();while (ring_buffer_valid_len(ring) >= 10){u32 end_time = sys_->get_timestamp();int dlt_time = (end_time > start_time) ? (end_time - start_time) : (start_time - end_time);if (dlt_time > timeout) {ring_buffer_pop(ring, &temp);break;}ring_buffer_get_value(ring, 0, &buff[0]);ring_buffer_get_value(ring, 1, &buff[1]);ring_buffer_get_value(ring, 2, &buff[2]);ring_buffer_get_value(ring, 3, &buff[3]);ring_buffer_get_value(ring, 4, &buff[4]);ring_buffer_get_value(ring, 5, &buff[5]);if ((pdata[0] == 0x66) && (pdata[1] == 0xAA)){if (pdata[5] == 0x02){if (ring_buffer_valid_len(ring) >= 13){for (int i = 0; i < 13; i++){ring_buffer_pop(ring, &mcu80ms_cmd->data[i]);}mcu80ms_cmd->fresh = 1;break;}}else if (pdata[5] == 0x03){for (int i = 0; i < 10; i++){ring_buffer_pop(ring, &mcutest_cmd->data[i]);}mcutest_cmd->fresh = 1;break;}else if (pdata[5] == 0x04){for (int i = 0; i < 10; i++){ring_buffer_pop(ring, &mcuiris_cmd->data[i]);}mcuiris_cmd->fresh = 1;break;}else{ring_buffer_pop(ring, &temp);}}else{ring_buffer_pop(ring, &temp);}}
}

通过直接操作UART接收的FIFO,进行命令块的数据提取。

6)接收处理,业务级函数

void MotorMcu::recv_loop()
{//解析mcu的反馈信息demux(&uart_->recv_buff, &mcu_cmd_);mcu2fpga_cmd_parse(&mcu_cmd_);//执行mcu的反馈mcu2fpga_cmd_action(&mcu_cmd_);
}

首先从FIFO中提取数据到mcu_cmd_结构体对象中,
然后解析mcu_cmd,
然后根据解析后的mcu_cmd,执行action.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
补充:
对定义的结构体对象,定义的对应的操作集,是全局的。
1)MCUCommand

void mcu2fpga_cmd_init(struct MCU2FPGACommand* cmd)
{memset(cmd, 0, sizeof(struct MCU2FPGACommand));
}void mcu2fpga_cmd_parse(struct MCU2FPGACommand* mcu_cmd)
{struct MCU80msCommand* mcu80ms_cmd = &mcu_cmd->mcu80ms_cmd;struct MCUTestCommand* mcutest_cmd = &mcu_cmd->mcutest_cmd;struct MCUIrisCommand* mcuiris_cmd = &mcu_cmd->mcuiris_cmd;mcu80ms_cmd_parse(mcu80ms_cmd);mcutest_cmd_parse(mcutest_cmd);mcuiris_cmd_parse(mcuiris_cmd);
}void mcu80ms_cmd_parse(struct MCU80msCommand* mcu80ms_cmd)
{int ret;if (!mcu80ms_cmd->fresh)return;mcu80ms_cmd->fresh = 0;mcu80ms_cmd->action = 0;ret = check_xor_crc(&mcu80ms_cmd->data[2], 9, mcu80ms_cmd->data[11]);if (ret < 0)return;unsigned char* pdata = (unsigned char*)&mcu80ms_cmd->data[0];mcu80ms_cmd->action = 1;mcu80ms_cmd->zoom_motor_value = (((unsigned short)pdata[7]) << 8) + ((unsigned short)pdata[6]);mcu80ms_cmd->focus_motor_value = (((unsigned short)pdata[8]) << 8) + ((unsigned short)pdata[9]);mcu80ms_cmd->zoom_limit = pdata[10] & 0x1;mcu80ms_cmd->focus_limit = (pdata[10] >> 1) & 0x1;mcu80ms_cmd->optics_fog_close_limit = (pdata[10] >> 2) & 0x1;mcu80ms_cmd->optics_fog_open_limit = (pdata[10] >> 3) & 0x1;
}void mcutest_cmd_parse(struct MCUTestCommand* mcutest_cmd)
{int ret;if (!mcutest_cmd->fresh)return;mcutest_cmd->fresh = 0;mcutest_cmd->action = 0;ret = check_xor_crc(&mcutest_cmd->data[2], 6, mcutest_cmd->data[8]);if (ret < 0)return;unsigned char* pdata = (unsigned char*)&mcutest_cmd->data[0];mcutest_cmd->action = 1;mcutest_cmd->filter_ok = pdata[7] & 0x1;mcutest_cmd->iris_ok = (pdata[7] >> 1) & 0x1;mcutest_cmd->zoom_ok = (pdata[7] >> 2) & 0x1;mcutest_cmd->focus_ok = (pdata[7] >> 3) & 0x1;
}void mcuiris_cmd_parse(struct MCUIrisCommand* mcuiris_cmd)
{int ret;if (!mcuiris_cmd->fresh)return;mcuiris_cmd->fresh = 0;mcuiris_cmd->action = 0;ret = check_xor_crc(&mcuiris_cmd->data[2], 6, mcuiris_cmd->data[8]);if (ret < 0)return;unsigned char* pdata = (unsigned char*)&mcuiris_cmd->data[0];mcuiris_cmd->action = 1;mcuiris_cmd->iris_limit_mode = pdata[7];
}

2)FPGA2MCUCommad

void fpga2mcu_cmd_init(struct FPGA2MCUCommand* cmd)
{memset(cmd->data, 0, sizeof(cmd->data));cmd->data[0] = 0x55;cmd->data[1] = 0xAA;cmd->data[2] = 0x02;cmd->data[3] = 0x0D;cmd->data[4] = 0x8F;cmd->data[5] = 0x0B;cmd->data[18] = 0xF0;cmd->len = 19;
}void fpga2mcu_set_zoom_field(struct FPGA2MCUCommand* cmd, u8 zoom_mode, u8 zoom_speed)
{cmd->data[6] = zoom_mode;cmd->data[7] = zoom_speed;
}void fpga2mcu_set_focus_field(struct FPGA2MCUCommand* cmd, u8 focus_mode, u8 focus_speed)
{cmd->data[8] = focus_mode;cmd->data[9] = focus_speed;
}void fpga2mcu_set_filter_field(struct FPGA2MCUCommand* cmd, u8 filter_mode, u8 filter_speed)
{cmd->data[10] = filter_mode;cmd->data[11] = filter_speed;
}void fpga2mcu_set_fov_value(struct FPGA2MCUCommand* cmd, u16 fov_value)
{cmd->data[12] = (fov_value >> 8) & 0xff;cmd->data[13] = fov_value & 0xff;
}void fpga2mcu_set_focus_value(struct FPGA2MCUCommand* cmd, u16 focus_value)
{cmd->data[14] = (focus_value >> 8) & 0xff;cmd->data[15] = focus_value & 0xff;
}void fpga2mcu_set_iris_field(struct FPGA2MCUCommand* cmd, u8 iris_mode)
{cmd->data[16] = iris_mode;
}void fpga2mcu_cmd_calc_crc(struct FPGA2MCUCommand* cmd)
{cmd->data[17] = calc_xor_crc(&cmd->data[2], 15);
}

++++++++++++++++++++++++++++++++++++++++++++++++++
这几个结构体中,使用了共享变量,用于各个函数之间的通信和同步。
这里使用的是标志变量,flag。
这里面,使用了两个flag,
fresh,action。

在parse函数中,会检查fresh的状态,决定是否执行后续代码,如果可以执行后续代码,则清除fresh的状态。这是一个原始的PV通信方式。
parse函数对fresh执行P操作,同步在fresh的状态上。
在parse函数中,会设置action的状态,从而使得其他的函数能够检查action的状态,然后决定是否执行。
parse函数对action执行V操作,是同步在action的状态上的函数,能够得以执行。

void mcuiris_cmd_parse(struct MCUIrisCommand* mcuiris_cmd)
{int ret;if (!mcuiris_cmd->fresh)return;mcuiris_cmd->fresh = 0;...mcuiris_cmd->action = 0;...mcuiris_cmd->action = 1;...
}

在action函数中,会检查action的状态,决定是否执行后续代码,如果可以执行后续代码,则清除action的状态。这是一个原始的PV通信方式。
action函数对action执行P操作,同步在fresh的状态上。

void MotorMcu::mcuiris_cmd_action(struct MCUIrisCommand* mcuiris_cmd)
{if (!mcuiris_cmd->action)return;mcuiris_cmd->action = 0;...
}

至此,我们看到,对于action标志,有函数执行V操作,作为上游同步者,也有函数执行P操作,作为下游同步者。
但是,对于fresh表示,有函数执行P操作,作为下游同步者,那么哪个函数执行V操作,作为上游同步者?
答案是demux。

void MotorMcu::demux(struct RingBuffer* ring, struct MCU2FPGACommand* mcu_cmd)
{...while (ring_buffer_valid_len(ring) >= 10){if ((pdata[0] == 0x66) && (pdata[1] == 0xAA)){if (pdata[5] == 0x02){if (ring_buffer_valid_len(ring) >= 13){...mcu80ms_cmd->fresh = 1;break;}}else if (pdata[5] == 0x03){...mcutest_cmd->fresh = 1;break;}else if (pdata[5] == 0x04){...mcuiris_cmd->fresh = 1;break;}...}...}
}

可以看到,demux中会设置fresh的值为1。

从SOD到OOD(MotorMCU模块)相关推荐

  1. 从SOD到OOD(spi_flash模块)

    D:\Xilinx\SDK\2019.1\data\embeddedsw\XilinxProcessorIPLib\drivers\spi_v4_4\examples 中 xspi_winbond_f ...

  2. 从SOD到OOD(AutoFocus模块)

    先来看看数据的封装 class AutoFocus {... public:SystemManager* sys_;const int max_steps_ = 16;int af_min_focus ...

  3. 从SOD到OOD(C++风格程序设计)

    https://www.runoob.com/ 这是一个很好的网站,可以找到各种教程. ++++++++++++++++++++++++++++++++ this指针 一个对象的this指针并不是对象 ...

  4. 从SOD到OOD(C++编码风格)

    https://zh-google-styleguide.readthedocs.io/en/latest/contents/# 这个Google C++风格指南 摘要如下: ++++++++++++ ...

  5. 机器学习回归模型精度_机器学习模型实施精度召回和概率截止。

    机器学习回归模型精度 Congratulations on completing your Machine Learning (ML) pipeline! In the second part of ...

  6. facebook是什么鬼_如果facebook是真正的沉默多数怎么办

    facebook是什么鬼 By Kevin Roose 凯文·罗斯 Listen, liberals. If you don't think Donald Trump can get reelecte ...

  7. 肯尼亚第三方支付_肯尼亚的COVID-19病例正在Swift增加,我们不知道为什么。

    肯尼亚第三方支付 COVID-19 cases in Kenya are accelerating rapidly. New cases have increased 300% month-over- ...

  8. EF-Net一种适用于双流SOD的有效检测模型(Pattern Recognition)

    论文地址:在公众号「3D视觉工坊」,后台回复「EF-Net」,即可直接下载. 简介 显著目标检测(SOD)在计算机视觉领域得到了广泛的关注.但面临低质量的深度图,现有模型的检测结果都不是很理想.为了解 ...

  9. 如何向妻子解释面向对象设计(OOD)

    前言 此文译自CodeProject上<How I explained OOD to my wife>一文,该文章在Top Articles上排名第3,读了之后觉得非常好,就翻译出来,供不 ...

最新文章

  1. android 图片列表,Android 列表使用(ListView GridView Gallery图片计时滚动)
  2. PC微信逆向:分析@群成员call
  3. Python 缓冲区
  4. tensorflow实现原理
  5. HarmonyOS之AI能力·关键字提取
  6. Js Vue 对象数组的创建方式
  7. 9.卷1(套接字联网API)---基本SCTP套接字编程
  8. 同网段的VLAN隔离
  9. 开发者,熊二都会的Linux入门
  10. OverTheWire的bandit游戏(11-20)
  11. 从控制台输入一个三位数,如果是水仙花数(是指一个三位数,其各位数字立方和等于该数 )就打印“是水仙花数”,否则打印“不是水仙花数”
  12. echarts使用rich设置显示数据label颜色
  13. cubic算法优化_安卓cpu优化 tcp拥塞算法cubic和reno怎么选择
  14. 算法很美第一章 位运算的奇巧淫技
  15. Android股票app模拟同花顺,适合练手的Android项目
  16. 苍穹角色对接流程开发
  17. Telegram-“只能给双向联系人发送消息”的错误信息
  18. React Demo Three - 简书掘金
  19. Win10系统的SurfacePro4的触摸笔如何使用
  20. cadence 16.60破解方式及文件下载地址

热门文章

  1. 美育在计算机教育中应用,音乐与信息技术学科整合,把美育融入到学校教育之中...
  2. 通过ssh工具,使PC远程连接机载电脑
  3. 皖西学院计算机专业男女比例,2018全国高校男女比例排行榜出炉!哪所大学最难找对象?...
  4. ASP.NET源码网站
  5. java | (三十一)MyBatis(1)配置、映射、缓存
  6. java并发之Semaphore信号量
  7. Ardunio-电视红外遥控,控制LeArm机械臂
  8. Out of range value for column 'phon' at row 1
  9. 赛码网_在线编程_约会
  10. 一些简单的java编程题(2) ————古典问题(兔子问题)