2019-01-17 15:13:26 qq_41616995 阅读数 374
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4006 人正在学习 去看看 朱有鹏

一、HSV 和 RGB 使用

1,概念:

      HSV:空间颜色,这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。

      RGB:光的三基色  R:红色    G:绿色     B:蓝色

2,RGB和HSV 之间联系

(1)每一种颜色可以用 RGB或则HSV来表示,RGB和HSV之间可以相互转换,HSV常用于色彩的搭配,用途更广。

(2)空间立体图

 

   

3,HSV和RGB相互转化

话不多说直接上代码

(1)RGB转HSV

static int rgb2hsv_max(int a,int b,int c)
{
	int max = a;

	if(b > max) max = b;

	if(c > max) max = c;

	return max;
}

 
static int rgb2hsv_min(int a,int b,int c)
{
	int min = a;

	if(b < min) min = b;

	if(c < min) min = c;

	return min;
}

int rgb2hsv(int r,int g,int b,int *h,int *s,int *v)
{
	int imax,imin,diff;
    int d_r=r*100/255;
	int d_g=g*100/255;
	int d_b=b*100/255;
	imax = rgb2hsv_max(d_r,d_g,d_b);
	imin = rgb2hsv_min(d_r,d_g,d_b);

	diff = imax - imin;

	*v = imax;
	if(imax == 0)
		*s = 0;

	else

		*s = diff;


	if(diff != 0)

	{

		if(d_r == imax)

		{

			*h = 60 * (d_g - d_b) / diff;

		}

		else if(d_g == imax)

		{

			*h = 60 * (d_b - d_r) / diff + 120;

		}

		else

		{

			*h = 60 * (d_r - d_g) / diff + 240;

		}

		if(*h < 0)

			*h = *h + 360;

	}

	else

		*h = -1;


	return 0;

}

(2)HSV转RGB

void hsv2rgb(unsigned char *r, unsigned char *g, unsigned char *b, int h, int s, int v)
{
    int i;
    float RGB_min, RGB_max;
    RGB_max = v*2.55f;
    RGB_min = RGB_max*(100 - s)/ 100.0f;

    i = h / 60;
    int difs = h % 60; // factorial part of h

    // RGB adjustment amount by hue
    float RGB_Adj = (RGB_max - RGB_min)*difs / 60.0f;

    switch (i)
    {
        case 0:
            *r = RGB_max;
            *g = RGB_min + RGB_Adj;
            *b = RGB_min;
            break;
        case 1:
            *r = RGB_max - RGB_Adj;
            *g = RGB_max;
            *b = RGB_min;
            break;
        case 2:
            *r = RGB_min;
            *g = RGB_max;
            *b = RGB_min + RGB_Adj;
            break;
        case 3:
            *r = RGB_min;
            *g = RGB_max - RGB_Adj;
            *b = RGB_max;
            break;
        case 4:
            *r = RGB_min + RGB_Adj;
            *g = RGB_min;
            *b = RGB_max;
            break;
        default:		// case 5:
            *r = RGB_max;
            *g = RGB_min;
            *b = RGB_max - RGB_Adj;
            break;
    }
}

 

2019-10-01 13:09:17 weixin_41645129 阅读数 35
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4006 人正在学习 去看看 朱有鹏

如何使用单片机开发小程序

单片机一般都是通过烧写hex或是bin文件来进行程序升级,这个方法是在8、16、32位单片机上常用的更新程序的方法。
这里实现单片机小程序的方法是通过在单片机上移植脚本来实现的。
目前我所了解的可以在单片机上跑的脚本有JerryScript、micropython、Lua。
因为脚本源码的代码量相对来说比较大,所以在8、16位的单片机一般不会使用到脚本开发。
在单片机上移植完后就是C、C++与脚本的互相通信,通过C、C++实现底层驱动、应用模块,将模块注册到脚本中,通过脚本调用。这样,只要通过更新文件系统中的脚本文件就可以实现在单片机上开发小程序,而不用通过烧写固件来升级程序。

2019-10-30 21:46:37 qq_44629109 阅读数 169
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4006 人正在学习 去看看 朱有鹏

单片机独立按键使用程序 (51单片机)

独立按键是单片机中很重要的一个器件,在这篇文章里,通过这个用独立按键控制LED灯的小程序来介绍独立按键开关的使用。

#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit key=P3^1; 
sbit led=P2^0;  

void delay(u16 num)//延时函数
{
 u16 x,y;
 for(x=num;x>0;x--)
  for(y=110;y>0;y--)
 {
  ;
 }
}
void main(void)
{
 led=1;
 while(1)
{
 if(key==0)
 {
  
  delay(10);//消抖程序
  if(key==0)
  {
  led=~led;//取反
  }
  while(!key);//使灯在开关下一次按下之前不发生变化,不跳出大循环
 }
}
}

两次按下按键的结果图
1

在这里插入图片描述

运行视频
在这里插入图片描述

2018-01-27 17:18:30 qq_34675909 阅读数 13267
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4006 人正在学习 去看看 朱有鹏

经过几天的努力,实现了在stm32单片机的RGB565图像简单处理,识别橘黄色乒乓球,同时单片机通过串口向上位机输出,乒乓球的重心坐标,和与图像中心线的夹角,在者可以输出的RGB565数据,通过c++读取输出的数据,转化为0~255范围中的单个r,g,b数值,产生一个txt文件,最后运行matlab程序,实现单片机颜色识别的的图像显示,由于单片机没有外接显示屏,所以采用c++和matlab实现数据的图像显示,所以过程比较繁琐,但是代码简单易懂,注释详细,stm32程序实在购买的开发板上做的修改,并非本人原创,其他为自己的原创上传资料仅供需要这方面的人参考,功能已经实现,资料包里面有单片机程序,c++,matlab程序,c++和MATLAB程序在一个文件夹,为运行方面,用c++6.0及以上,matlab应该都兼容,下面是图像展示(上传资料请到本人主页查找)

下载链接https://download.csdn.net/download/qq_34675909/10227246

2018-11-26 09:36:25 SheepTech 阅读数 699
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4006 人正在学习 去看看 朱有鹏





文章原始地址:http://feotech.com/?p=25




基于Unique ID的单片机程序加密系统 单片机唯一ID程序加密

单片机一般作为一个产品的逻辑中心,工作时一直在进行着逻辑判断与执行操作,相当于人类的大脑。单片机可以通过修改程序来控制外围电路的工作状态,从而改变产品的功能。如果一个产品具有单片机,那么它往往是这个产品的核心。而开发一款功能复杂且成熟的产品所需要的费用不低并且研发周期较长,一些个人为了某些原因,为了快速仿造竞争对手的产品,一般就原样照抄对方的硬件电路,但由于单片机内部有针对产品功能单独设计的程序,不能直接再市面上购买,所以就只能想办法通过特殊的解密方法将单片机内部的程序读取出来。将解密后读取出来的程序烧录在新的芯片中从而完成产品功能的抄袭。通过专用的设备和工具,利用单片机芯片设计上的硬件漏洞或软件缺陷,通过多种技术手段获取单片机内程序这叫做单片机解密或单片机破解。以不正当方式获得其他公司或个人的商业秘密,是一种常见的不正当竞争行为。单片机加密技术是对产品知识产权保护的一种技术手段。

Unique ID加密原理

当前市面上的单片机资源中大多数具有Unique ID,即每一个芯片内部均具有唯一的芯片ID号。不同的芯片厂家实现该功能的方式不同,一些用生产线的流水号,另一些是用晶圆的特性来生成ID。 利用Unique ID加密的方法流程如下:

单片机一般作为一个产品的逻辑中心,工作时一直在进行着逻辑判断与执行操作,相当于人类的大脑。单片机可以通过修改程序来控制外围电路的工作状态,从而改变产品的功能。如果一个产品具有单片机,那么它往往是这个产品的核心。而开发一款功能复杂且成熟的产品所需要的费用不低并且研发周期较长,一些个人为了某些原因,为了快速仿造竞争对手的产品,一般就原样照抄对方的硬件电路,但由于单片机内部有针对产品功能单独设计的程序,不能直接再市面上购买,所以就只能想办法通过特殊的解密方法将单片机内部的程序读取出来。将解密后读取出来的程序烧录在新的芯片中从而完成产品功能的抄袭。通过专用的设备和工具,利用单片机芯片设计上的硬件漏洞或软件缺陷,通过多种技术手段获取单片机内程序这叫做单片机解密或单片机破解。以不正当方式获得其他公司或个人的商业秘密,是一种常见的不正当竞争行为。单片机加密技术是对产品知识产权保护的一种技术手段。

Unique ID加密原理
当前市面上的单片机资源中大多数具有Unique ID,即每一个芯片内部均具有唯一的芯片ID号。不同的芯片厂家实现该功能的方式不同,一些用生产线的流水号,另一些是用晶圆的特性来生成ID。 利用Unique ID加密的方法流程如下:

A. 将单片机烧录程序A后上电运行程序,完成加密操作。
B. 将单片机烧录程序最终程序B,该程序包含ID识别部分。 加密流程图如下:
这里写图片描述

  • 程序A负责读取芯片内部的Unique ID,并进行加密运算。将运算的结果写入芯片内部的EEPROM。
  • 程序B是实现产品最终功能的程序,该程序其中加入了产品身份识别功能。该程序首次上电后将首先读取EEPROM数据,并进行与加密算法相同的逆向算法,将加密后的数据进行解密获得芯片Unique ID。将解密后的ID与当前芯片的ID进行比对,如果数据不同则判断为非法程序。

加密算法

为了防止破解者通过仿真的方式找到芯片ID信息,一般不宜直接存放ID号。而是经过相应的加密处理后写入存储器中。校验方式也不宜采用常见、简单的校验规则,应尽可能采用某些特殊的检验方式,使破解者不能迅速确定校验算法。
加密的算法类似数学公式 Y=F(X) 其中Y为加密以后的数据,X为原始数据,而F则为加密算法。
加密算法有很多种,本实验中采用简单的位移后取反的方式来进行数据加密。

这里写图片描述
最后将加密的数据存入EEPROM中,由于芯片的ID厂家不允许更改,这大大增加了破解难度,加强了对产品的保护。

详细设计过程
使用Unique ID对单片机程序加密功能的实现需要以下几点功能:
① 实验板1用于对程序加密实验。
② 将从实验板1中读取到的数据烧录到实验板2中,通过实验板上的LED状态验证程序加密是否成功。
基于Unique ID的单片机程序加密分为2个程序,这2个程序是不同的。
程序A:用于读取芯片硬件ID并进行算法处理,将处理后的数据保存到EEPROM中。
程序B:用于将EEPROM中的数据读取出来并使用与加密相同的算法进行解密获得芯片ID,将解密后获得的ID与芯片本身的ID进行比较。比较结果只有2种可能,即为相同与不同,程序根据结果从而执行不同的操作如图所示;

这里写图片描述
实验中使用STM8S单片机作为硬件载体

软件设计

系统初始化函数选择了内部16MHz时钟源,1分频后系统总线时钟频率为16MHz。
将GPIO与EEPROM擦写均进行了初始化配置。 函数代码如下:

void SystemInit(void)
{
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);    //总时钟源 使用内部时钟源1分频 16M/1分频 =16MHz
    Gpio_Init(); //单片机系统GPIO初始化 FLASH_DeInit();//存储数据的EEPROM初始化
    FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);// 默认的EEPROM写入时间
}

LED驱动程序

根据硬件的电路原理图可以看出,LED连接到PE5引脚。采用灌电流驱动,当引脚为低电平时LED点亮,引脚为高电平时LED熄灭。上电后LED默认为熄灭状态,所以引脚初始化配置为高速输出模式高电平。函数代码如下:

/*描述:MCU外围GPIO初始化*/
/*输入:无*/
void Gpio_Init(vod)
{
    //功能引脚上电初始化,引脚初始化状态根据外部功能而定义//
    GPIO_Init(GPIOE, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST); //LED
}

LED的状态采用宏定义方式,直接控制IO管脚电平状态。 操作代码如下:

/*LED操作宏定义*/
#define LED_ON GPIO_WriteLow(GPIOE, GPIO_PIN_5); //点亮LED
#define LED_OFF GPIO_WriteHigh(GPIOE, GPIO_PIN_5); //熄灭LED

获取Unique ID程序

STM8S105K4T6数据手册显示该芯片具有96bit Unique ID,96bit/8=12byte。存放ID的起始地址为0x48CD,从该地址读取12次,将芯片ID获取并存入数组。 函数代码如下:

/*描述:获取芯片ID*/
/*输入:存放芯片ID的数组*/
/*输出:无*/
/*参数:无*/
void Get_ChipID(unsigned char *p)//Get chip ID
{
    unsigned char i=0; for(i=0; i<12; i++) //读取12次
    {
        *p = *(u8*)(0X48CD+i); //将数据读出后进行存放
        p++;
    }

获取Unique ID程序

STM8S105K4T6数据手册显示该芯片具有96bit Unique ID,96bit/8=12byte。存放ID的起始地址为0x48CD,从该地址读取12次,将芯片ID获取并存入数组。
函数代码如下:

/*描述:获取芯片ID*/
/*输入:存放芯片ID的数组*/
/*输出:无*/
/*参数:无*/
void Get_ChipID(unsigned char *p)//Get chip ID
{
    unsigned char i=0;
    for(i=0; i<12; i++) //读取12次
    {
        *p = *(u8*)(0X48CD+i); //将数据读出后进行存放
        p++;
    }
}

加密算法程序

编码函数执行对Unique ID进行数据算法处理。实验中采用的算法为将存放Unique ID的数组进行左移三个元素后逐位取反。将编码后的数据存入另一个数组。
编码函数代码如下:

/*描述:对芯片ID进行编码处理*/
/*输入:存放芯片ID的数组;存放芯片ID编码后的数组*/
/*输出:无*/ /*参数:对输入数组左移三次后逐位取反*/
void Encode(unsigned char *DataIn,unsigned char *DataOut)//对数据进行编码加密
{
    unsigned char i;//数组数据左移次数 unsigned char j;//数据位移临时局部变量
    unsigned char DataSwap;//搬运数据用的临时变量
    unsigned char TempData[12];//数据处理交换变量数组
    for(i=0;i<12;i++)//数据数组交换
    {
        TempData[i] = *DataIn; DataIn++;
    }
    for(i=0;i<3;i++)
    {
        //数组元素左移操作
        DataSwap = TempData[0];
        for(j=0;j<11;j++) //数组左移搬运
        {
            TempData[j] = TempData[j+1]; } TempData[11] = DataSwap;
        }
    for(i=0;i<12;i++)
    {
        TempData[i] = ~ TempData[i] ; //对数组数据进行按位取反
        *DataOut = TempData[i] ; DataOut++;
    }
}

解密算法程序

解码函数负责对从EEPROM中读取的数据进行解码,是编码函数的一个逆向算法处理。算法为将输入的数组(EEPROM数据)进行右移三个元素后按位取反。示意图如下:
这里写图片描述
函数如下

/*描述:对从EEPROM读出的数据进行解码*/
/*输入:存放编码数据的数组,存放解码数据的数组*/
/*输出:无*/
/*参数:数据右移三位后按位取反(算法)*/
void Decode(unsigned char *DataIn,unsigned char *DataOut)
{
  unsigned char i;//数组数据左移次数
  unsigned char j;//数据位移临时局部变量
  unsigned char DataSwap;//搬运数据用的临时变量
  unsigned char TempData[12];//数据处理交换变量数组
  for(i=0;i<12;i++)//数据数组交换
  {
    TempData[i] = *DataIn; DataIn++;
  }
  for(i=0;i<3;i++)//数据右移三次
  {
    //数组元素右移操作
    DataSwap = TempData[11]; 
    for(j=10;j>0;j--)//数组右移搬运
    {
      TempData[j+1] = TempData[j];
    }
    TempData[1] = TempData[0];
    TempData[0] = DataSwap;//最后一次搬运
  }
  for(i=0;i<12;i++)//对数组数据进行诸位取反
  {
    TempData[i] = ~ TempData[i] ;
    *DataOut = TempData[i];
    DataOut ++;
  }
}

数据写入EEPROM程序

将编码处理后的数据写入EEPROM,存储器起始地址为0x000040A0,通过单字节写入。将12个字节全部写入EEPROM。函数代码如下:

/*描述:EEPROM数据写入*/
/*输入:数据源的数组*/
/*输出:无*/
/*参数:无*/
void EEPROMWrite(unsigned char *p)
{
  unsigned char i;//数据交换用局部临时变量
  FLASH_Unlock(FLASH_MEMTYPE_DATA); //解锁EEPROM,允许写入数据
  while( !(FLASH_GetFlagStatus(FLASH_FLAG_DUL)) );//等待EEPROM解锁完成
  for(i=0;i<12;i++)
  {
    FLASH_ProgramByte(0x000040A0+i, *p);//将数据写入EEPROM,写入存储起始地址为0x000040A0
    while( !( FLASH_GetFlagStatus(FLASH_FLAG_EOP)) );//等待EEPROM单次写入完成
    p++;
  }
  FLASH_Lock(FLASH_MEMTYPE_DATA); //锁定EEPROM
}

从EEPROM读出数据程序

程序首先需要从EEPROM中读取加密后的数据,将数据保存到数组EncodeData中。程序代码如下:

/*描述:读取芯片EEPROM数据*/
/*输入:用于存放EEPROM的数组*/
/*输出:无*/
/*参数:*/
void Get_EEPROMData(unsigned char *p)
{
  unsigned char i=0; for(i=0; i<12; i++)
  {
    *p = FLASH_ReadByte(0x40A0 + i);//从EEPROM读取数据
    p++;
  }
}

数据比对程序

数据比对函数负责将解密后数据与Unique ID两个数组的数据进行比对。该函数只有两个返回结果,数据完全相同与不同,返回不同的值。根据不同的返回值从而判断程序是否合法。函数代码如下:

/*描述:将两个数据进行比对*/
/*输入:要比对的数据A,要比对的数据B*/
/*输出:比对结果 1:数据相同 0:数据不同*/
/*参数:对数组进行按字节比对*/
unsigned char IDCheck(unsigned char *a,unsigned char *b)
{
  unsigned char i; unsigned char Flag;//比对结果标志 1:数据相同 0:数据不同
  Flag = 1; for(i=0;i<12;i++)
  {
    if( (*a) != (*b) ) { Flag = 0; } a++; b++;
  }
  return Flag;//返回值:比对结果标志 1:数据相同 0:数据不同
}

数据数组
使用数组的存储芯片ID与编码加密后的数据。代码如下:

/*数组定义*/
unsigned char Chip_IDData[12]; //存放芯片
Unique ID unsigned char EnCodeData[12]; //对芯片Unique ID编码加密后的数据
unsigned char DecodeData[12]; //对芯片EEPROM解密后的数据

A程序主函数代码
本程序主要作用是将数据进行加密编码处理并将结果写入EEPROM, 程序的主函数调用上方的单元功能函数。

/*描述:主函数*/
/*输入:无*/
/*输出:无*/
/*参数:无*/
void main(void)
{
  SystemInit(); //系统初始化
  Get_ChipID(Chip_IDData); //获取芯片 ID并存储在数组
  Encode(Chip_IDData,EnCodeData); //编码运算处理
  EEPROMWrite(EnCodeData); //将编码数据写入
  EEPROM LED_ON; //写入完成后点亮LED
  while(1); //软件循环
}

运行该程序后,将读取到的芯片ID数据存入数组。通过内部编码算法函数将ID进行处理并写入EEPROM。程序运行流程图如图所示:
这里写图片描述

B程序主函数代码
程序B作用为对EEPROM数据读取并进行解码处理后判断程序合法性。主函数代码如下:

/*描述:Main主函数*/
/*输入:无*/
/*输出:无*/
/*参数:无*/
void main(void)
{
  SystemInit(); //系统初始化
  Get_ChipID(Chip_IDData);//获取芯片自身ID Get_EEPROMData(EncodeData);

  //从EEPROM读取编码后的数据 
  Decode(EncodeData,DecodeData);//将编码数据进行解码 //将解码后的数据与当前芯片ID进行比对
  if(IDCheck(Chip_IDData,DecodeData))
  {
    //返回1 比对通过,芯片与ID身份识别通过
    LED_ON; //点亮LED
  }
  else
  {//比对失败 程序非法
    LED_OFF; //熄灭LED
    While(1); //死循环
  }
  while(1)
  {
    ; //程序正常执行循环
  }
}

解码程序为最终烧录到芯片中的程序,产品功能也是在次此结构下开发的。程序执行后会读取当前芯片自身的Unique ID与存储在EEPROM中的数据。将EEPROM中的数据进行解码后与Unique ID进行比对,当数据完全相同时判断程序合法并执行正常程序功能,当数据比对不相同后判断程序非法并执行相应操作。解码程序运行流程图如图所示:
这里写图片描述
系统测试
这里写图片描述

将运行B程序后的实验板1通过通过仿真器与电脑连接,将STVP切换到“Program Memory”选项卡后点击“Read curren tab of active sectors”按钮后读取数据。在菜单File->save中选择保存程序B。(模拟程序被解密)

将读取的程序B烧录到实验板2中,观察LED的现象。
烧录程序B后实验板1测试LED亮起,实验板2测试LED未亮起。
这里写图片描述
测试结果
从实验中可以看到,实验板二虽然烧录了程序B,但是之前并没有运行过程序A的加密算法,所以程序识别出EEPROM解密后数据与芯片自身ID不匹配从而熄灭LED。
本文所设计的系统已经通过上述过程的测试,可以满足对单片机程序加密的功能需求。

当前加密系统中需要完善的部分
程序中仅仅有1处判断程序合法性,一旦遭到反编译后容易被破解
程序被判断为非法后没有保护操作,应加入强制擦除 Flash进行保护
程序需要烧录2次来完成整个加密系统的流程. 应在程序中加入启动加密条件,实现一次程序烧录即可完成加

单片机程序框架

阅读数 482

单片机程序框架

博文 来自: qq_41262681

MSP430单片机的框架程序

博文 来自: baicaiye
没有更多推荐了,返回首页