您的位置:首页 > 教育 > 锐评 > 桂林北站附近住宿_唐山做网站建设的公司_谷歌关键词分析工具_网络平台建设及运营方案

桂林北站附近住宿_唐山做网站建设的公司_谷歌关键词分析工具_网络平台建设及运营方案

2025/2/28 9:20:53 来源:https://blog.csdn.net/2301_81831368/article/details/145866454  浏览:    关键词:桂林北站附近住宿_唐山做网站建设的公司_谷歌关键词分析工具_网络平台建设及运营方案
桂林北站附近住宿_唐山做网站建设的公司_谷歌关键词分析工具_网络平台建设及运营方案

一,Seg

底层:

高电平灭,共阳极

‘,’的ASCII码是44

不消隐的话:

显示完3,想显示5:显示5时有视觉残留

消隐:

显示完3,想显示5:流程:先显示3,然后显示空白,最后显示5

#include "seg.h"

// 0-9 灭

//  A

code unsigned char seg_dula[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82, 0xf8, 0x80, 0x90, 0xff,

0x88};

void Seg_Disp(unsigned char wela, unsigned char dula, unsigned char point) {

  // 消隐

  P0 = 0xff;

  P2 = P2 & 0x1f | 0xe0;

  P2 &= 0x1f;

  // 位选

  P0 = 0x01 << wela;

  P2 = P2 & 0x1f | 0xc0;

  P2 &= 0x1f;

  // 段选

  P0 = seg_dula[dula];

  if (point) P0 &= 0x7f;

  P2 = P2 & 0x1f | 0xe0;

  P2 &= 0x1f;

}

void Timer1_Isr(void) interrupt 3:

    // 数码管显示处理

    if (Seg_Buf[Seg_Pos] > 20)

    Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos] - ',', 1); // 带小数点

    else

    Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos], 0); // 无小数点

void Seg_Proc():

Seg_Buf[0] = 9 + ',';

二,c语言里的结构体,c++里的类

三,本质上调度器还是从上到下运行,得把数码管放最后面

保证显示的数据,是获取之后的数据

不然:

数据还没更新,或数据更新了,但没丢到数码管里,

数码管显示的数据(可能是上次的数据)和真实的数据不一样

四,led可以同时点亮(不要1ms点亮一个)

好处:led的pwm,亮度等级

底层:

输入:ucLed[]={1,0,1,0,1,0,1,0};

Temp_1=0101 0101

 idata  unsigned char temp_1 = 0x00;

 idata  unsigned char temp_old_1 = 0xff;

void Led_Disp(unsigned char *ucLed)

{

   temp_1=0x00;

   temp_1 = (ucLed[0] << 0) | (ucLed[1] << 1) | (ucLed[2] << 2) | (ucLed[3] << 3) |

         (ucLed[4] << 4) | (ucLed[5] << 5) | (ucLed[6] << 6) | (ucLed[7] << 7);

  if (temp_1 != temp_old_1)

  {

    P0 = ~temp_1;

    P2 = (P2 & 0x1f) | 0x80;

    P2 &= 0x1f;

    temp_old_1 = temp_1;

  }

}

void Led_Off()

{

    P0 = 0xff;

    P2 = (P2 & 0x1f) | 0x80;

    P2 &= 0x1f;

    temp_old_1=0x00;

}

void Timer1_Isr(void) interrupt 3:

idata unsigned char pwm_period=10;          //pwm调光周期,单位为毫秒

idata unsigned char pwm_compare=5;          //pwm调光占空比,0-10可调,初始为5

  if(++pwm_period==10)pwm_period=0;//pwm计数自增

  if(pwm_period>=pwm_compare)//pwm计数比较

  {

  Led_Disp(ucLed); // LED显示更新

  }

  else//熄灭led

  {

    Led_Off();

   

  }

void Led_Proc():

void Led_Proc()

{

   // Led处理逻辑可以在这里添加

   //如题目没有要求pwm调光时,可将Led_Disp函数放到此处刷新led以减少定时器1中断的执行时间

  //Led_Disp(ucLed); // LED显示更新

}

五,中断一般都是运行判断,也可以运行处理函数,最好别。

中断时间过长影响代码

六,filtering硬件的问题,软件滤波来弥补(防止测到的数据突变)

冒泡排序:

通过多次遍历,未排序部分的最大(或最小)元素会逐渐“浮”到列表的顶端,就像气泡一样

内循环一次,把最大的数 排到 最高位

外循环十次,十个数小到大(这里:sorted_data[j] > sorted_data[j + 1],交换位置) 依次排

sorted_data[10]={低, , , , , , , , ,高};

中值滤波函数:

代码有问题:刚进一个数据,滤波后,中间值不是就0了吗

群友改进:(不一定对)

数据个数>=3,用中值滤波,

数据个数<3,用第一个数据替代

#include <Filtering.h>

#include <string.h>

#define N 10 // 滤波窗口大小

pdata int data_array[N]={0}; // 存储窗口内的数据

pdata int index = 0; // 当前数据的索引

// 中值滤波器函数

// 参数:new_data - 新的输入数据

// 返回值:滤波后的数据

int Median_Filter(int new_data)

{

  idata  int sorted_data[N];

  idata     int i, j, temp;

   

    // 复制数据到临时数组

    for (i = 0; i < N; i++) {

        sorted_data[i] = data_array[i];

    }

    // 冒泡排序

    for (i = 0; i < N - 1; i++)

    {

      for (j = 0; j < N - i - 1; j++)

      {

            if (sorted_data[j] > sorted_data[j + 1])

            {

                // 交换元素位置

                temp = sorted_data[j];

                sorted_data[j] = sorted_data[j + 1];

                sorted_data[j + 1] = temp;

            }

      }

    }

    data_array[index] = new_data; // 存储新数据

    index = (index + 1) % N; // 更新索引

    return sorted_data[N / 2]; // 返回中值

}

滑动平均滤波函数:

计算信号在一定窗口内的平均值来替代当前采样值,从而抑制高频噪声。

这里返回平均值有问题:应该这样 没十个时,有几个除几,满了后,除十

Index_2初始为0,下面代码不一定对

if(Index_2<N)

return sum/Index_2;

else

return sum/N;

#define N 10 // 滤波窗口大小

pdata int data_array_2[N]={0}; // 存储窗口内的数据

pdata int sum = 0; // 存储窗口内数据的和

pdata int index_2 = 0; // 当前数据的索引

// 滑动平均滤波器函数

// 参数:new_data - 新的输入数据

// 返回值:滤波后的数据

unsigned  int Moving_Average_Filter(unsigned  int new_data)

{

    sum -=  data_array_2[index_2]; // 减去窗口中被替换的数据

    data_array_2[index_2] = new_data; // 存储新数据

    sum += new_data; // 计算新的和

    index_2 = (index_2 + 1) % N; // 更新索引

    return sum / N; // 返回平均值

}

七,温度,中值滤波(排出去,找一段时间的中值),让温度低图形更加平滑

idata unsigned int temputure_100x;    // 温度数据x100

/*温度读取函数*/

void Get_temputure(void)

{

 unsigned int temp =  rd_temperature() * 100;

 temputure_100x= Median_Filter(temp);

}

八,超声波,滑动平均滤波,先排序(一个一个值丢),避免超声波突然变化

超声波数据,一直流进数组(10个值),流进一个到数组,把最旧的数值丢了

数组返回平均值

/*超声波测距读取函数*/

void Get_distance(void)

{

    unsigned int temp = Ut_Wave_Data();

    distance= Moving_Average_Filter(temp);

}

九,STARTUP.A51是51的启动文件(新建工程时,问要不要添加进去):

负责初始化堆栈、清除 RAM、配置硬件环境,并最终跳转到 main 函数。

通过自定义 STARTUP.A51,可以优化单片机的启动行为,确保程序能够正确运行。

debug时用

十,Beep,Motor,Relay底层

必须要用同一个全局变量:不然Beep,Motor,Relay任意两者同时使用时,会数据覆盖,

导致不能同时工作

idata unsigned char temp_0 = 0x00;

idata unsigned char temp_old_0 = 0xff;

/// @brief 蜂鸣器控制

/// @param enable

void Beep(bit enable)

{

  if (enable)

    temp_0 |= 0x40;

  else

    temp_0 &= ~(0x40);

  if (temp_0 != temp_old_0)

  {

    P0 = temp_0;

    P2 = P2 & 0x1f | 0xa0;

    P2 &= 0x1f;

    temp_old_0 = temp_0;

  }

}

/// @brief 继电器控制

/// @param enable

void Relay(bit enable)

{

  if (enable)

    temp_0 |= 0x10;

  else

    temp_0 &= ~(0x10);

  if (temp_0 != temp_old_0)

  {

    P0 = temp_0;

    P2 = P2 & 0x1f | 0xa0;

    P2 &= 0x1f;

    temp_old_0 = temp_0;

  }

}

/// @brief MOTOR控制

/// @param enable

void MOTOR(bit enable)

{

  if (enable)

    temp_0 |= 0x20;

  else

    temp_0 &= ~(0x20);

  if (temp_0 != temp_old_0)

  {

    P0 = temp_0;

    P2 = P2 & 0x1f | 0xa0;

    P2 &= 0x1f;

    temp_old_0 = temp_0;

  }

}

舵机Motor(向外输出高低电平)考点:PWM波

SIG_OUT(P34连接)是测ne555

十一,Key按键8,9同时按下

按列扫描:刚好按键8,按键9在同一列

P44 = 1;P42 = 0;P35 = 1;//P34 = 1;用到ne555,注释掉P34

if(P33 == 0&&P32 == 0) temp = 89;

但按键在调度器10ms扫描一次,10ms内同时按下?

按键扫描时间不能给太长:

按键时间越长,消抖效果越好,但按键生效越晚(按键的反应精度不够),界面切换时间不达标

但10ms按不了双按键,那就改成20ms

万一双按键,既不同行,又不同列

行列扫描:

uint16_t是16位,按键是16个:1位代表一个按键

哪两个按键同时=1,说明哪两个按键同时按下

十二,Key

#include "key.h"

unsigned char Key_Read() {

  unsigned char temp = 0;

//  ET1 = 0; 串口发送,用到中断,如果按键进去,可能导致中断崩一下,会频繁的开关中断

           

  P44 = 0;

  P42 = 1;

  P35 = 1;

  //P34 = 1;

  if (P33 == 0) temp = 4;

  if (P32 == 0) temp = 5;

  if (P31 == 0) temp = 6;

  if (P30 == 0) temp = 7;

  P44 = 1;

  P42 = 0;

  P35 = 1;

  //P34 = 1;

  if (P33 == 0) temp = 8;

  if (P32 == 0) temp = 9;

  if (P31 == 0) temp = 10;

  if (P30 == 0) temp = 11;

  P44 = 1;

  P42 = 1;

  P35 = 0;

  //P34 = 1;

  if (P33 == 0) temp = 12;

  if (P32 == 0) temp = 13;

  if (P31 == 0) temp = 14;

  if (P30 == 0) temp = 15;

/*

  P44 = 1;

  P42 = 1;

  P35 = 1;

  P34 = 0;

  if (P33 == 0) temp = 16;

  if (P32 == 0) temp = 17;

  if (P31 == 0) temp = 18;

  if (P30 == 0) temp = 19;

*/

//  P3 = 0xff;//防止串口出问题

//  ET1 = 1;

  return temp;

}

  • 烧录时,蜂鸣器叫:正常现象

十四,ds1302

void Set_Rtc(unsigned char *ucRtc)//十进制存放的

{

unsigned char i;

Write_Ds1302_Byte(0x8e,0x00);

for(i=0;i<3;i++)

{

Write_Ds1302_Byte(0x84-2*i,ucRtc[i]/10%10<<4|ucRtc[i]%10);

或 Write_Ds1302_Byte(0x84-2*i,ucRtc[i]/10%10*16+ucRtc[i]%10);

}

Write_Ds1302_Byte(0x8e,0x80);//写保护是不让写

}

void Read_Rtc(unsigned char* ucRtc)十进制读出

{

unsigned char i,temp;

EA=0;读时间需要关中断(有时候读时间会,时间会跳一个0出来:读时会延时,导致中断乱掉一下)

for(i=0;i<3;i++)

{

temp = Read_Ds1302_Byte(0x85-2*i);//读位置跟写位置 不一样

ucRtc[i] = temp/16%16*10+temp%16;

}

EA=0;

}

  • ds18b20

仿真要注意,不要乘12

ds18b20手册第十页:

如果有多个ROM,就会检查,但板子上只有一个ROM,检查需要花时间,所以跳过

float rd_temperature()

{

unsigned char low,high;

init_ds18b20();

Write_DS18B20(0xcc);//跳过ROM

Write_DS18B20(0x44);//启动温度转换

Delay_OneWire(200);//等待转换完成

init_ds18b20();

Write_DS18B20(0xcc);

Write_DS18B20(0xbe);//读取温度值

low = Read_DS18B20();

high = Read_DS18B20();

return (float)((high << 8) | low) / 16.0;//或*0.0625精度值

}

手册第三页:

12位精度 对应 0.0625刻度

(温度传感器用户可配置为9,10,11或12位,对应于0.5°C的增量;分别为0.25℃、0.125℃和0.0625℃。开机时的默认分辨率是12位。)

10位/11位,读取出来后,分辨率降低,但最终还是乘0.0625

(值的精度会变,整体算法不变)

手册第八页:

十六,上位机 发信息 给单片机,用sscanf(按照相对格式读取)在串口函数里 进行字符串 比对

sscanf解析里面的数据

strcmp比较

十七,pdata,idata内存区间的划分,逻辑上可以全用pdata或idata,只差了几纳秒

十八,IIC,PCF8591

读底层:

AD:0~5v到0~255:temp是0~255 写地址,读数字量

unsigned char Ad_Read(unsigned char addr) //写PCF8591;写定位;读PCF8591;读一个数字

{

  unsigned char temp;

  // 选择芯片为PCF

  I2CStart();

  I2CSendByte(0x90);

  I2CWaitAck();

  I2CSendByte(addr);

  I2CWaitAck();

  I2CStart();

  I2CSendByte(0x91);

  I2CWaitAck();

  temp = I2CReceiveByte();

  I2CSendAck(1);

  I2CStop();

  return temp;

}

写底层:

是0~255 写数字

void Da_Write(unsigned char dat) //写PCF8591;打开Da通道;写一个数字量

{

  // 选择芯片为PCF

  I2CStart();

  I2CSendByte(0x90);

  I2CWaitAck();

  I2CSendByte(0x41);

  I2CWaitAck();

  I2CSendByte(dat);

  I2CWaitAck();

}

用法:

idata unsigned int AD_in_100x;        // AD输入的数据x100

idata unsigned int DA_out_100x = 100; // DA输出的数据x100

void AD_DA(void)

{

  AD_in_100x = Ad_Read(0x43) * 100 / 51;

  Da_Write(DA_out_100x * 51 / 100);

}

void Seg_Proc()

{

printf("%u,%u,%u,%u\n", temputure_100x / 100, distance, AD_in_100x / 100, Freq / 1000);

}

十九,写ds1302时

AIN0外部输入AIN1光敏电阻,AIN2差分输入(没考过)AIN3滑动变阻器

I2CSendByte(0x41);

0100 0001:0x41光敏电阻(开启DA)

0100 0011:0x43滑动变阻器(开启DA)

第零位:0

第一位:1是否开启模拟输出(是否开启DA)开启为1

第二三位:00用AIN0

第四位:0

第五位:0自动递增,先给个0号,下一刻读取1号,下一刻读取2号,我们要手动,所以0

第六七位:读取哪个通道

AIN0外部输入,AIN1光敏电阻,AIN2差分输入(没考过),AIN3滑动变阻器

SCH_V31第四页

二十,IIC挂载很多外设:9是1001代表PCF8591

二十一,AT24C02写入四个delay,防止连续写入出问题

二十二,超声波

1/40 000 000=0.000000025s=

超声波需要12.5us,但ISP只能生成12us,自己把33改成38

二十三,超声波读取用PCA定时器

定时器0测ne555,定时器1定时1ms (调度器),定时器2串口

二十四,超声波算0.017时,要把单位化成cm/us

L= V米每秒 * T/2

超声波测距是测量声波发出去和反射回来是时间间隔,用微秒做单位。

空气中的声速是340m/s=3400cm/s=0.034cm/us

时间要÷2

65536μs最大探测距离是65536×0.017=1114厘米=11.14米

二十五,while((Rx==1)&&(TF1==0));//数据读取未结束,没溢出:循环

二十六,uart

底层:

串口12MHZ,串口1,9600,8位数据,定时器2,12T

串口重定向printf

return ch是自带的格式

不用在.h里声明,(可能是因为extern),自动把这个函数编进去

如果自己的代码写了putchar,不会用系统的putchar,而是用自己的

extern char putchar(char ch)

 {

  SBUF = ch;

  while (TI == 0);

  TI = 0;

  return ch;

}

/* 串口处理函数 */

void Uart_Proc()

{

  if (Uart_Rx_Index == 0)

    return; // 无数据,直接返回

  if (Uart_Recv_Tick >= 10)

  { // 若接收超时,对数据读取,清空缓存区

Uart_Recv_Tick = 0;

if(Uart_Buf[0]==A&&Uart_Buf[1]==B)

{

//如果接受到AB

}

    memset(Uart_Buf, 0, Uart_Rx_Index); // 清空接收数据

    Uart_Rx_Index = 0;

  }

}

/* 串口1中断服务程序 */

void Uart1_Isr(void) interrupt 4

{

  if (RI)

  {                                   // 若接收到数据

    Uart_Recv_Tick = 0;               // 清零接收时间标志

    Uart_Buf[Uart_Rx_Index++] = SBUF; // 将数据保存到缓冲区

    RI = 0;                           // 清除接收中断标志

    if (Uart_Rx_Index > 10)

    Uart_Rx_Index = 0; // 防止溢出

  }

}

二十七,idata访问速度比pdata快一点,可以全用idata(但怕idata爆),xdata比这两个都慢

二十八,key_val和key_old差10ms(为什么)

二十九,keil5,help,uvision help,搜printf,

printf c51library routine,要打印什么数据,有对应的类型

三十,sscanf解析固定格式

发送数据出来,有一个相关的格式,

你是知道我会发这个格式出来的

sscanf读取

sscanf(str,"%d,%d",i,j);

前面的值%d给i,后面的给j

把逗号搞没了

三十一,调度器如果时间撞上了,优先从上往下

led放下面也好一点

每个人板子性能有区别,多少ms调度一次不一定

三十二,初始化顺序有讲究,定时器1要最后初始化,整个系统开始运行

三十三,刚上电延时750ms,让设备跑起来,尤其是ds1302上电读取的时候是85

三十四,

ptr: 指向要填充的内存区域的指针。

value: 要填充的值,以 int 形式传递,但函数会将其转换为 unsigned char。

num: 要填充的字节数。

char str[50];

将 str 数组的所有字节初始化为 'A'

memset(str, 'A', 50);

int arr[10];

将 arr 数组的所有字节初始化为 0

memset(arr, 0, sizeof(arr));

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com