/*
免费程序,您可以任意修改与发布。
C++位运算演示程序
从串口监视工具输入数字,可以是二进制/八进制/十进制/十六进制
测试的二进制与十进制效果不错,其余进制的数未测试。
显示结果用10位的光条显示,比较直观。
已知问题:
NOT运算的结果可能是错的
*/
#include "converter.h"
#include "String.h"
const int xTyping = 0; //正在输入x值
const int yTyping = 1; //正在输入y值
String x = ""; //接收到的x字符串
String y = ""; //接收到的y字符串
int xValue = 0; //保存x值
int yValue = 0; //保存y值
int flag; //输入进度标识,输入x/输入y/输入运算符选项
int pinFirst = 29; //光条第一脚IO口位置
int pinLast = 38; //光条最后脚IO口位置
Converter converter; //声明转换类变量
void setup()
{
Serial.begin(9600);
flag=xTyping;
for (int i=pinFirst; i<=pinLast; i++)
pinMode(i,OUTPUT);
Diagnose(); //测试光条是否正常
}
void loop()
{
if (Serial.available()>0)
{
char c;
c=Serial.read();
String str;
if (c=='\n') //字符串结束标识
{
switch (flag)
{
case xTyping:
Serial.print("x = ");
Serial.println(x); //显示接收到的字串
Serial.print("x in binary base: ");
xValue = converter.StrToInt(x); //转换成数字
str= converter.toBinary(xValue);//转换成二进制,并且用光条显示出来
Serial.println(str);
displayStrWithLED(str);
Serial.println("");
break;
case yTyping:
Serial.print("y = ");
Serial.println(y);
Serial.print("y in binary base: ");
yValue=converter.StrToInt(y);
str = converter.toBinary(yValue);
Serial.println(str);
displayStrWithLED(str);
Serial.println("");
Serial.println("Please select the bitwise operator ");
Serial.println(" 1: & bitwise AND");
Serial.println(" 2: | bitwise OR");
Serial.println(" 3: ^ bitwise XOR");
Serial.println(" 4: ~ bitwise NOT");
Serial.println(" 5: << bitwise LEFT");
Serial.println(" 6: >> bitwise RIGHT");
Serial.print("");
Serial.print("Your choice: ");
}
flag ++;
flag=flag % 3;
}
else
{
if (flag == xTyping) //将收到的字符拼接成字符串
x +=c;
else if(flag==yTyping)
y+=c;
else
{
Serial.println(c); //CHECK
doBitwiseOperate(c);
}
}
}
}
void displayFormula(char op, boolean full)//显示公式,第一个参数是运算符,
//第二个参数是决定是否显示y,NOT运算不显示y
{
Serial.print(" ");
Serial.println( converter.toBinary(xValue));
Serial.print(" ");
switch (op)
{
case '<':
Serial.print("<<");
break;
case '>':
Serial.print(">>");
break;
default:
Serial.print(" ");
Serial.print(op);
}
Serial.print(" ");
if (full)
Serial.println( converter.toBinary(yValue)); //NOT运算不显示y
else
Serial.println("");
Serial.println("-----------------");
Serial.print(" = ");
}
void doBitwiseOperate(char opt)
{
String result="";
Serial.println("");
switch (opt)
{
case '1': //bitwise AND
displayFormula('&',true);
result = converter.toBinary( xValue &=yValue);
break;
case '2': // bitwise OR
displayFormula('|',true);
result = converter.toBinary(xValue |= yValue);
break;
case '3': //bitwise XOR
displayFormula('^',true);
result = converter.toBinary(xValue ^= yValue);
break;
case '4': //bitwise NOT
Serial.println("NOT operation is not well supported yet"); //NOT运算涉及到负数,有时候会出现错误
Serial.println("");
displayFormula('~',false);
yValue = ~ xValue;
xValue = yValue;
result = converter.toBinary(xValue );
break;
case '5': //bitwise LEFT
displayFormula('<',true);
result = converter.toBinary(xValue << yValue);
break;
case '6': //bitwise RIGHT
displayFormula('>',true);
result = converter.toBinary(xValue>>yValue);
}
Serial.println(result);
displayStrWithLED(result);
x="";
y="";
xValue=0;
yValue=0;
Serial.println("");
Serial.println("");
Serial.println("");
}
void Clear()
{
for (int i=pinFirst; i<=pinLast; i++) //清楚前面的显示结果
digitalWrite(i,LOW);
}
void Diagnose() //诊断光条是否正常
{
for (int i=pinFirst; i<=pinLast; i++)
{
digitalWrite(i,HIGH);
delay(50);
}
delay(500);
for (int i=pinLast; i>=pinFirst; i--)
{
digitalWrite(i,LOW);
delay(50);
}
}
void displayStrWithLED(String value)
{
Clear();
for (int i=0; i<value.length(); i++)
{
if (value[i]=='1')
digitalWrite(i+pinFirst,HIGH);
else
digitalWrite(i+pinFirst,LOW);
}
}
下面是转换类的代码:
Exported from Notepad++
Exported from Notepad++
#ifndef CONVERTER_H
#define CONVERTER_H
#include "Arduino.h"
#include "String.h"
//#include "types.h"
enum Alignment
{
alLeft,
alCenter,
alRight
};
class Converter
{
private:
int getActualSize(String value);
public:
Converter();
unsigned int StrToInt(String value);
String toBinary(int value);
String toBinary(int value, Alignment align);
void setDelimeter(char value);
};
#endif // CONVERTER_H
#include "converter.h"
/*
将字符转换成数字
数字字串的字头
b or B for binary numbers,
o or O for oct,
d or D for decimal,
and h or H for hex,
if no flag char exists, the number would be consider a decimal.
if the number entered is an illegal one, then return -1.
This class could NOT handle negative numbers.
*/
#define errValue -1 //字串中如果有无效的字符,则返回-1
//#include <iostream>
using namespace std;
char delimeter;
int Power(int base, int power) //This is an equivalent of pow, but this one only handle integer, however.
{
int v = 1;
switch (power)
{
case 0:
return 1;
break;
case 1:
return base;
break;
default:
for (int i = 1; i <= power; i++)
v *= base;
}
return v;
}
int binStr2Int(String value, int len)
{
int v = 0;
for (int i = 1; i <= len ; i++)
{
switch (value[i])
{
case '0':
break;
case '1':
v += Power(2, len - i);
break;
default:
return errValue;// exit the function early when it runs into error
}
}
return v;
}
int octStr2Int(String value, int len)
{
int v = 0;
int c;
for (int i = 1; i <= len ; i++)
{
c = value[i];
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
v += ((c - '0') * Power(8, len - i));
break;
default:
return errValue;
}
}
return v;
}
int decStr2Int(String value, int len)
{
int v = 0;
int c;
c = value[0];
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
break;
case 'd':
case 'D':
value[0] ='0';
len++;
break;
default:
return errValue;
}
char t;
for (int i = 0; i <= (len-1 ); i++)
{
t = value [i];
switch (t)
{
case '0':
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
v += Power(10, len -1 - i )*(t-'0');
break;
default:
v = errValue;
}
}
return v;
}
int hexStr2Int(String value, int len)
{
int v = 0;
int c;
for (int i = 1; i <= len ; i++)
{
c = value[i];
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
v += ((c - '0') * Power(16, len - i));
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
v += ((c - 'A' + 10) * Power(16, len - i));
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
v += ((c - 'a' + 10) * Power(16, len - i));
break;
default:
return errValue;
}
}
return v;
}
unsigned int lenOfString(String value) //字符长度
{
int result =0;
char terminal= value[0];
while (terminal!=delimeter)
{
result ++;
terminal = value [result];
}
switch (value[0])
{
case 'b':
case 'B':
case 'o':
case 'O':
case 'd':
case 'D':
case 'h':
case 'H':
result --;
}
return result ;
}
unsigned int Converter::StrToInt(String value)
{
char c;
unsigned int result;
int len;
len = lenOfString(value);
c= value[0];
switch (c)
{
case 'b':
case 'B':
result = ::binStr2Int(value,len);
break;
case 'o':
case 'O':
result = octStr2Int(value, len);
break ;
case 'd':
case 'D':
result = decStr2Int(value,len);
break;
case 'h':
case 'H':
result = hexStr2Int(value,len);
break;
default:
result = decStr2Int(value,len);
}
return result ;
}
Converter::Converter()
{
delimeter = '\0'; //输入时字串的结束标志
}
void Converter::setDelimeter(char value)
{
delimeter=value ;
}
String Converter::toBinary(int value)
{
return toBinary(value, alRight);
}
String Converter::toBinary(int value, Alignment align)
{
String result="0000000000";
char bin[10]={
'0000000000' };
itoa(value,bin,2);
//#define DEBUG;
#ifdef DEBUG
Serial.println("");
Serial.println("********************************");
Serial.println("parse bin[]");
for (int i=0; i<10; i++)
{
Serial.print(bin[i]);
Serial.print("->");
Serial.println(bin[i],DEC);
}
Serial.println("length of bin[]");
int len;
//len= sizeof(bin)/sizeof(bin[0]); //return 10, which is declared before, is not the actural size data occupied, however.
len = getActualSize(bin);
Serial.println(len);
Serial.println("end of parsing bin[]");
Serial.println("********************************");
#endif
if (align==alLeft)
result = bin;
else
{
int len;
len = getActualSize(bin);
int offset = 10- len;
for (int i=0; i<len; i++)
result[i+offset] = bin[i];
}
return result;
}
int Converter::getActualSize(String value)
{
int result = 0;
for (int i=0; i<10; i++)
{
if (value[i]=='\0')
{
result= i;
break;
}
}
return result;
}
手头上还有几个8*8的LED点阵,用它来做应该更加直观,哪天改改。
没有评论:
发表评论