标题：蒙器M&H-08控制器
M&H-08控制器简介
M&H-08控制器为新型32位ARM7主板，如下图所示：
特点：运算速度快，程序容量大，接口齐全，稳定可靠。
软件环境：MiniRobot软件（一种标准C语言，支持指针和结构等）进行程序开发。
下载方式：兼容USB口和串口下载。
特点
M&H-08控制器使用了3级流水线技术，处理和存储系统的所有部分都可连续工作。通常在执行一条指令的同时对下一条指令进行译码，并将第三条指令从存储器中取出。因此其速度大约是普通处理器的3倍。
M&H-08控制器使用了一个被称为Thumb 的独特结构化策略， Thumb是一种“超精简指令集”。其指令集约为标准代码两倍的密度，却仍然保持性能上的优势，这些优势是传统16 位处理器所不具备的。因此使用Thumb程序大小仅为标准代码的3/4，但其性能却相当于16 位处理器系统的性能的160%。
M&H-08控制器使用128MHz的主频， AVR处理器系统的4倍，因此，更适合高速的处理应用。数据存储器M&H-08控制器含有256K字节的Flash 存储器系统。该存储器可用作代码和数据的存储。存储器至少可擦除/编程100,000 次，保存数据的时间长达20年。该存储器至少可以存储约1万行的C代码。其容量约为AVR处理器系统的10倍。另外加上32K字节的数据存储器，因此非常适合实现更复杂，更庞大的应用。信号输入通道M&H-08控制器集成了14路高速信号采集通道，可以兼容数字信号和模拟信号，每路精度为10位，因此可以分辨3毫伏特的输入电压变化。14路数据通道均为高速数据采集通道，每秒可以采集40万次输入信号。DO输出通道M&H-08控制器包含了6路最大电流为0.5A的数字信号输出通道，可直接驱动蜂鸣器，继电器以及其他的输出设备。机输出通道M&H-08控制器集成了两路大功率电机驱动输出，最大电压约为40V，最大瞬间电流约为40A。并且使用独立的电源供电，避免了大功率电机对主板的电磁干扰。串行接口M&H-08控制器具有标准串行通信接口，进行数据采集和程序下载。并且可以连接摄像头、指南针等高级模块。USB接口M&H-08控制器具有的USB接口，可以非常方便的下载程序和进行数据采集，适合大多数没有串口的笔记本电脑使用。
第二章
快速入门
所需设备
所需设备如下表所示：
M&H-08控制器 
USB线或串口线 
7.2V锂电池 
使用手册 
工具 
电脑 
2.2.安装软件
安装前，请在光盘中按顺序安装如下软件：
.NET Framework 2.0 
M&H-08MiniRobot 
这些软件可以运行在Windows 98，Me，2000，XP等系统上，不能在Windows 95、Mac OS或linux上安装。
2.3.安装USB驱动
使用USB端口下载程序前请按以下步骤安装：
A: 打开控制器主板电源
主板电源插槽 
主板电源开关 
B：用USB线连接电脑和控制器。
USB接口 
C：打开控制器主板电源，您会见到电脑右下角弹出一个找到新硬件的提示框，如下图所示：
D：弹出找到新硬件向导后，请选择红色框中的选项。然后点击下一步。
在随后的对话框中，请选择“列表或指定位置安装”，然后点击下一步。
在随后的对话框中，请选择“请选择您的搜索和安装路径选项”中的“在这些位置上搜索最佳驱动程序”选项，再选择“在搜索中包括这个位置”选项。最后点击浏览按钮，输入USB驱动程序路径，您可以在光盘上或者M&H-08 MiniRobot安装目录下找到这个驱动程序。设置完成后,请点击下一步。
弹出如下对话框，表示USB驱动安装完成。您可以开始进行模块编辑了。
2.4. 启动程序
请双击  这个图标，启动M&H MiniRobot软件。在弹出的启动对话框中选择“EasyC代码编辑器for M&H-08控制器”，点击确定。
如下图将显示编写代码。
2.5.下载程序
使用USB下载或串口下载程序，我们建议您使用USB，这样既方便又快速。请打开控制器主板电源，然后，点击“菜单”---“下载”或者工具条上的“下载”按钮，启动下载。在下载过程中，请不要拔去USB线，以防意外的程序下载终止。下载完成时，请拔去USB连接线，然后按控制器主板上的运行按钮，就能看到在屏幕上显示“M&H”字样。
第三章  M&H-08控制器详细说明
M&H-08控制器可直接安装各类传感器，无需叠加任何扩展卡。
M&H-08控制器常用设备，如图所示 ：
{指示灯，运行和复位按钮，主板电源和大功率电源接口，信号输入接口（模拟口和数字口输入接口），电机输出接口，DO信号输出接口，USB接口，串行接口。}
显示屏 
指示灯 
6个信号输入口和6个数字输出口
复位按钮 
运行按钮 
大功率电源开关
8个信号输入口
大功率电源插槽
主板电源开关 
串口下载口 
指南针接口 
USB下载口 
主板电源插槽
复位按钮 
大功率电源插槽 
电机2插槽 
电机1插槽 
3.1.运行和复位按钮
主板上有两个按钮，其中一个是运行按钮，一个是复位按钮。
运行程序使用运行按钮，中断程序使用复位按钮。
当用串口下载程序时，先按住运行按钮，然后按一下复位按钮，最后放掉运行按钮即可。
3.2 电源接口
M&H-08控制器的主板电源和大功率电机驱动卡的电源是分别供电的。主板电源接口有防反接保护，即使反接也不会烧坏主板。但是大功率电源没有防反接保护，在使用时需要特别小心。
3.3 信号输入接口
M&H-08控制器集成了14路信号采集通道，可以兼容数字信号和模拟信号，每路精度为10位， 连接电路请参考以下电路：其中S标记为信号输入。
3.4 电机输出接口
大功率电机输出接口共有两路，每路允许最大电压达到40V，最大电流达到40A。
使用M&H-08 MiniRobot（一种标准C语言），只需调用库函数SetMoto(char Channel, signed char Speed)即可设置电机速度和方向。
3.5 DO信号输出接口
输出电压大于4V,电流不大于0.5A。
当驱动继电器时，直接连接继电器将导致主板损坏，您可参考以下电路来改装普通的继电器，仅仅是在继电器的线圈出并联了一个二极管，并且请注意二极管的正负极（反接可能导致主板损坏）。
您还可以使用M&H-08 MiniRobot（一种标准C语言），调用库函数SetDO(char Channel, char State)即可设置数字输出。
3.6 USB接口
当您编写完程序后，请按照以下步骤下载程序：
第一：确保您的控制器与电脑间通过附件中的USB线正确连接。
第二：打开控制器主板电源
第三：点击“下载”按钮或菜单栏上的“编译”—“下载”即可。
注意：在此过程中请勿按动运行和复位按钮，或中断电源，否则USB下载将意外终止,这可能导致USB固件损坏，在此情况下，您还是可以通过串行端口进行修复操作，方法是点击菜单“编译”—“下载固件”然后选择合适的串行端口和波特率，并且可以修复字库丢失等错误，注意此过程将持续约4分钟左右。
3.7 串行接口
除了USB接口，您也可以使用串行端口下载程序。方法是点击菜单“编译”—“设置”。如图：如果使用串行端口，波特率推荐选用38400。如果使用USB，则无需设置波特率
设置完成后。请按照以下步骤下载程序：
第一：确保您的控制器与电脑间通过附件中的串口线正确连接。
第二：打开控制器电源 
第三：点击“下载”按钮或菜单栏上的“编译”—“下载”。
第四：按住运行按钮不放，然后按一次复位按钮，最后放掉运行按钮。
串口下载可能需要30秒左右，这取决于您的程序大小和波特率的快慢。
第四章  M&H-08控制器软件编程指南
4.1 屏幕显示函数
printf函数的定义：int printf(const char *fmt,…);
如果要在屏幕上显示“M&H”，参考程序如下：
/*主函数，每个c语言必须有一个主函数*/
void main()
{
/*在屏幕上显示“M&H”字样*/
printf("M&H                       ");
}
“ ”空格代表清屏，
如果要在屏幕上显示一个动态的数字，例如一个变量或者一个传感器的读数，参考程序如下：
/*主函数，每个c语言必须有一个主函数*/
void main()
{
/*定义一个变量，名称为i,整型变量（即是整数的，没有小数点的数字）*/
int i=0;
/*不断的循环，重复执行{}之间的程序代码*/
while(1)
{
/*变量i加1，然后再保存到变量i中*/
i=i+1;
/*将变量i显示到屏幕上，其中空格是清屏*/
printf("value=%d                          ",i);
}
}
最终，您将会看到屏幕上动态的显示一个不断累加的数字。您是否发现了一个奇怪的问题，“%d”为何没有被显示出来， “%d”表示在这个位置需要显示一个十进制的整数，这个整数就是逗号后面的变量i。如果您要显示两个变量，参考程序如下：
void main()
{
/*定义两个变量，名称为i，j,整型变量（即是整数的，没有小数点的数字）*/
int i=0;
int j=0;
/*不断的循环，重复执行{}之间的程序代码*/
while(1)
{
/*变量i加1，然后再保存到变量i中*/
i=i+1;
/*变量j加2，然后再保存到变量j中*/
j=j+2;
/*将变量i,j显示到屏幕上，空格的作用是清屏*/
printf("valuei=%d, valuej=%d                             ",i,j);
}
}
注意事项：由于在屏幕上显示文字和图象所需时间大概为几十毫秒，因此在您需要高速处理数据的时候，请尽量避免使用屏幕显示程序。
4.2设置电机函数
M&H-08控制器提供了3种函数来控制电机，如下表所示：
/*启动电机，左右轮运行函数，iVL为直线速度，iVR为旋转速度*/
void Drive(signed char iVL, signed char iVR); 
/*停止电机运行*/
void Stop(void); 
/*启动电机，Channel为电机编号,MF MOS电机驱动器使用1或2， Speed为电机速度，-90到90之间*/
void SetMoto(char Channel,singed char Speed) 
建议使用SetMoto这个函数，因为其功能最强， Drive和Stop都可以用此函数代替，这样，您只需记住一个函数的用法即可。
驱动电机，参考程序如下：
void main()
{
While(1)
{
/*机器人正转一秒然后反转一秒*/
SetMoto(1,90);
SetMoto(2,90);
wait(1.0);
SetMoto(1,-90);
SetMoto(2,-90);
wait(1.0);
}
}
SetMoto 函数中，“1”和“2”分别表示M&H-08控制器两个电机输出通道，分别表示左电机和右电机，来控制电机的功率和旋转方向。
注意事项：.屏幕显示会影响到电机输出的方向信号，所以请尽量避免同时使用电机和屏幕。
4.3 模拟口函数
M&H-08控制器通过传感器将各种物理化学信号转化为电信号，输入到控制器的模拟输入口。使用模拟口的传感器如下：电子复眼、光电开关、红外测距、红外测障、地面灰度、声音传感器和碰撞开关等。
读取模拟口的函数定义：
/*读取模拟输入口的读数，iCh为通道，返回0-1023*/
int AI(unsigned char iCh); 
参考程序如下：
/*主函数，每个c语言必须有一个主函数*/
void main()
{
/*定义变量*/
int i=0;
/*循环14次，每隔一秒钟显示一个通道的值*/
for (i=0 ; i<14 ; i++)
{
/*清屏，并显示AI(读取的通道) = 读取值*/
printf("AI(%d) = %d                          ",i,AI(i));
/*延时1秒*/
wait(1.0);
}
} 
传感器连接模块需要在程序开头处放置一些全局变量，数量的多少取决于您所接传感器数量。
如果要读取端口1上的地面灰度传感器，参考程序如下：
int GROUND;
GROUND = AI(1);
如果要实现一个简易的数字万用表的功能，即将得到模拟口数据转换为电压并显示到屏幕上，参考程序如下：
void main()
{
float voltage=0.0;
while(1)
{
/*电压转换*/
voltage=AI(0)*3.3/1023;
/*清屏，显示转换的电压值*/
printf("voltage=%fV                          ",voltage);
}
}
注意事项：为了保证M&H-08控制器的输入口的可靠稳定，硬件上加上了模拟口电压保护，即超过5V电压加到模拟口上短时间内不会损坏控制器。
4.5  设置DO函数
如果要在DO口的安装一个发光二极管（注意：发光二极管需要串联一个470-2K欧姆的电阻以防止烧坏），参考程序如下：
/*全局变量,发光二极管所接的DO端口*/
int DOPORT       = 1;
void main()
{
while (1)
{
/*点亮发光二极管*/
SetDO(DOPORT,1);
/*延时0.5秒*/
wait(0.5);
/*熄灭发光二极管*/
SetDO(DOPORT,0);
/*延时0.5秒*/
wait(0.5);              
}
}
您可以编写程序，实现连续可调亮度的台灯等功能。让发光二极管以特定频率不断闪烁，频率高到人眼无法发觉它的闪烁，然后，控制每一次闪烁时点亮和熄灭的时间比例，就能控制它的亮度。实际上，这种控制方式还用在电机驱动上，这就是通常说的PWM控制原理。如果您要控制发光二极管的亮度，参考程序如下：
/*全局变量,发光二极管所接的DO端口*/
int DOPORT       = 1;
void main()
{
int i;
int LightOn= 0;
int FecTime=10000;
int DPWM = 10;
int inv=0;
while (1)
{
SetDO(DOPORT,1);/*点亮发光二极管*/
for(i = 0;i<LightOn;i++){}/*延时等待,时间间隔为LightOn*/
SetDO(DOPORT,0);/*熄灭发光二极管*/
for(i = 0;i<(FecTime-LightOn);i++){}/*延时等待,时间间隔为FecTime-LightOn*/
if( inv == 0)
{
LightOn=LightOn+DPWM; /*增加点亮的时间*/
}
else
{
LightOn=LightOn-DPWM; /*减少点亮的时间*/
}
if(LightOn>FecTime)
{
inv=1; /*如果点亮时间到达最大,则需要减少点亮时间*/
}
else if(LightOn<0)
{
inv=0; /*如果点亮时间到达最小,则需要增加点亮时间*/
}
}
}
4.5 读取指南针函数
M&H-08控制器通过串口读入指南针的数据。
读取指南针的函数：Compass_Degree（），其显示数值范围是0—360度。应用指南针时，程序开头处必须先要初始化串行端口波特率为9600，参考程序如下：
void main()
{    
int sci_1;
/*初始化串口,使用指南针前必须调用该函数*/
SCI_Set(0,9600,0,8,1 );
while(1)
{
/*读取指南针的数据*/
sci_1=Compass_Degree();    
/*显示出来*/    
printf("compass=%d                        ",sci_1);
}
}
附录1   库函数定义及说明
//启动电机,左右轮运动函数,iVL为直线速度，iVR为旋转速度
void Drive(signed char iVL, signed char iVR);
//电机停止运行
void Stop(void);
//设置电机,Channel为电机编号（或）。speed为电机速度，范围为-100到100之间
void SetMoto(char Channel, signed char Speed);
//在屏幕上输出文字。例如：printf("value=%d                    ",val);
int printf(const char *fmt, ...);
//读取模拟口通道的输入。iCh为通道号0-13。返回0-1023
int AI(unsigned char iCh);
//设置DO数字输出，DO为通道号(0-5)，state为状态，为高电平，为低电平
void SetDO(char DO,char State);
//串口设置函数。请使用如下设置：SCI_Set(0,9600,0,8,1)
void SCI_Set(char iPort,unsigned int iBaud,char iCHK, char iData, char iStop);
//使用串口发送单个字节数据。iPort为接收端口号，设为0。data为单个字节的数据0-255
void SCI_Send(char iPort, unsigned char data);
//串口接收函数,从串口读取一个数据。iPort为接收端口号，设为0
int  SCI_Receive(char iPort);
//延时等待毫秒，del为等待时间，单位为毫秒
void DelayMs(unsigned long del);
//延时等待，fTime为等待时间，单位为秒
void wait(float fTime);
//红外线测障传感器函数。DO_out为红外发射头接上的数字输出口，AI_in为红外接收头接上的模拟输入通道号
int ir_detector(int DO_out,int AI_in);
//读取麦克风的监测结果，ch为麦克风接上的模拟输入通道号(0-23)
int microphone(char ch);
//清屏。number为1表示用黑色清屏，0表示用白色清屏
void CLRVLCD(unsigned char number);
//绘制Buf缓冲区中的数据到屏幕上
int PrintfVLCD(unsigned char *Buf);
//在屏幕上绘制一个像素点，x，y为坐标点，color为1表示绘制黑色点，color为0表示绘制白色点
void PutPixelVLCD(unsigned char X, unsigned char Y, char Color);
//将内存的缓冲区复制到屏幕缓冲区上
void CpyVLCDToLCD(void);
//绘图函数,画直线,color： 1指定黑,0指定白
void DrawLine(int x1,int y1,int x2,int y2,int color);
//绘制矩形.(top,left)表示矩形顶点的坐标,width表示矩形的宽度,height表示矩形的高度,color 1指定黑,0指定白
void DrawRect(int top,int left,int width,int height,int color);
//画圆弧.x,y表示圆心坐标,r表示圆半径,startAngle表示启示角度,sweepAngle表示终止角度,color 1指定黑,0指定白
void DrawArc(int x,int y,int r,int startAngle,int sweepAngle,int color);
//读取指南针,返回0-358。该函数使用前需要调用初始化串口函数
int Compass_Degree();
//数学函数：返回长整型变量的绝对值。
long labs(long   val);
//数学函数：返回整型变量的绝对值。
int abs(int    val);
//数学函数：返回浮点型变量的绝对值。
double fabs(double val);
//数学函数：返回双精度变量val平方根
double sqrt(double val);
//数学函数：返回自然数e的val次方
double exp(double val);
//数学函数：返回log(val)
double log(double val);
//数学函数：返回log10(val)
double log10(double val);
//数学函数：返回val的正弦值。角度value 必须用弧度表示。乘以π/180 将角度转换成弧度。
double sin(double val);
//数学函数：返回val的余弦值。角度value 必须用弧度表示。乘以π/180 将角度转换成弧度。
double cos(double val);
//数学函数：返回val的正切值。角度value 必须用弧度表示。乘以π/180 将角度转换成弧度。
double tan(double val);
//数学函数：返回val的反正弦值。
double asin(double val);
//数学函数：返回val的反余弦值。
double acos(double val);
//数学函数：返回val的反正切值。
double atan(double val);
//数学函数：返回val指定角度的双曲正弦值。角度value 必须用弧度表示。乘以π/180 将角度转换成弧度。
double sinh(double val);
//数学函数：返回val指定角度的双曲余弦值。角度value 必须用弧度表示。乘以π/180 将角度转换成弧度。
double cosh(double val);
//数学函数：返回val指定角度的双曲正切值。角度value 必须用弧度表示。乘以π/180 将角度转换成弧度。
double tanh(double val);
//数学函数：返回正切值为两个指定数字的商的角度。返回值为笛卡尔平面中的角度，该角度由X 轴和起点为原点(0,0)、终点为(x,y) 的向量构成。
double atan2(double y, double x);
//数学函数：返回大于或等于其数字参数的最小整数.例如：ceil(45.998)返回
double ceil(double val);
//数学函数：返回小于或等于指定数字的最大整数。例如：Floor(2.10)返回
double floor(double val);
//数学函数：返回val变量分割成整数部分和小数部分。例如：x = 123.456;frc_part = modf (x, &int_part);结果为frc_part=123，int_part=0.456
double modf(double val, double *n);
//数学函数：The fmod function calculates the floating-point remainder f of x / y such that x = i * y + f, where i is an integer, f has the same sign as x, and the absolute value of f is less than the absolute value of y.
double fmod(double x, double y);
//数学函数：返回指定数字的指定次幂。数字x 的y 次幂
double pow(double x, double y);
附录2   技术参数
内核 CPU ARM7，32位 
程序存储器 256k字节，其中128k字库，32KUSB固件，用户可用96k 
数据存储器 32k用户全部可用 
流水线 3级流水线 
时钟 128MHz 
指令 Thumb是一种“超精简指令集” 
接口 数据输入通道 14路高速，2.5us每通道每次，兼容数字和模拟信号 
DO信号输出 6路，0.5A每路 
大功率电机通道 2路，瞬间电流<40A每路，耐压<40V 
指南针 串口读入 每秒27次 
下载口 USB口/串口下载 兼容