/*
    免费程序,您可以任意修改与发布。
    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点阵,用它来做应该更加直观,哪天改改。
