分析此段代码unsigned long HX711_Read(void) //读取711读到的数据 { unsigned long val = 0; unsigned char i = 0; float p; GPIO_SetBits(ADIO,DATA); GPIO_ResetBits(ADIO,CLK); while(GPIO_ReadInputDataBit(ADIO,DATA)); delay_us(1); for(i=0;i<24;i++) { GPIO_SetBits(ADIO,CLK); val=val<<1; delay_us(1); GPIO_ResetBits(ADIO,CLK); if(GPIO_ReadInputDataBit(ADIO,DATA)) val++; delay_us(1); } GPIO_SetBits(ADIO,CLK); val = val^0x800000; delay_us(1); GPIO_ResetBits(ADIO,CLK); delay_us(1); p=val; return p; }
时间: 2024-03-22 16:40:40 浏览: 84
这段代码的功能是读取HX711传感器的值,返回一个无符号长整型数。该函数的实现采用了GPIO控制IO口实现读取。其具体步骤如下:
1. 将DATA口置高电平,CLK口置低电平。
2. 等待DATA口状态变为低电平,即等待传感器准备就绪。
3. 循环24次,每次在CLK口置高电平后,将当前读取到的数据左移一位,然后读取DATA口的状态,若为高电平,则将val的最低位设为1。
4. 将CLK口置高电平,再将读取到的数据异或0x800000,然后将CLK口置低电平。
5. 返回读取到的数据val。
需要注意的是,该函数返回的数值并不是物品的实际重量,还需要进行一定的转换才能得到准确的物品重量。
相关问题
写出下列代码每行的注释: #include<reg51.h> sbit SN_green=P0^3; sbit SN_yellow=P0^4; sbit SN_red=P0^5; sbit EW_green=P0^0; sbit EW_yellow=P0^1; sbit EW_red=P0^2; unsigned char data cnt_sn,cnt_ew; unsigned int data T1_cnt; unsigned char data state_val_sn,state_val_ew; char code led_seg_code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; char code init_sn[3]={24,4,29}; char code init_ew[3]={29,24,4}; void delay(unsigned int t) { while(--t); } void led_show(unsigned int u,unsigned int v) { unsigned char i; i=u%10; P1=led_seg_code[i]; P3=0xef; delay(50); P3=0xff; i=u%100/10; P1=led_seg_code[i]; P3=0xdf; delay(50); P3=0xff; i=v%10; P2=led_seg_code[i]; P3=0xbf; delay(50); P3=0xff; i=v%100/10; P2=led_seg_code[i]; P3=0x7f; delay(50); P3=0xff; } void timer1() interrupt 3 { T1_cnt++; if(T1_cnt>3999) { T1_cnt=0; if(cnt_sn!=0) { cnt_sn--; } else { state_val_sn++; if(state_val_sn>2)state_val_sn=0; cnt_sn=init_sn[state_val_sn]; if(state_val_sn==0) { SN_green=0; SN_yellow=1; SN_red=1; } else if(state_val_sn==1) { SN_green=1; SN_yellow=0; SN_red=1; } else if(state_val_sn==2) { SN_green=1; SN_yellow=1; SN_red=0; } } if(cnt_ew!=0) { cnt_ew--; } else { state_val_ew++; if(state_val_ew>2)state_val_ew=0; cnt_ew=init_ew[state_val_ew]; if(state_val_ew==0) { EW_green=1; EW_yellow=1; EW_red=0; } else if(state_val_ew==1) { EW_green=0; EW_yellow=1; EW_red=1; } else if(state_val_ew==2) { EW_green=1; EW_yellow=0; EW_red=1; } } } } void button1() interrupt 0 { cnt_sn=60; cnt_ew=60; SN_green=1; SN_yellow=1; SN_red=0; EW_green=1; EW_yellow=1; EW_red=0; } main() { cnt_sn=init_sn[0]; cnt_ew=init_ew[0]; T1_cnt=0; state_val_sn=0; state_val_ew=0; SN_green=0; SN_yellow=1; SN_red=1; EW_green=1; EW_yellow=1; EW_red=0; TMOD=0x20; TH1=0x19; TL1=0x19; EA=1; ET1=1;TR1=1; IT1=1;EX1=1; IT0=1;EX0=1; while(1) { delay(10); led_show(cnt_sn,cnt_ew); } }
#include<reg51.h> //包含头文件reg51.h
sbit SN_green=P0^3; //定义P0^3为SN_green
sbit SN_yellow=P0^4; //定义P0^4为SN_yellow
sbit SN_red=P0^5; //定义P0^5为SN_red
sbit EW_green=P0^0; //定义P0^0为EW_green
sbit EW_yellow=P0^1; //定义P0^1为EW_yellow
sbit EW_red=P0^2; //定义P0^2为EW_red
unsigned char data cnt_sn,cnt_ew; //定义cnt_sn和cnt_ew为无符号字符型变量
unsigned int data T1_cnt; //定义T1_cnt为无符号整型变量
unsigned char data state_val_sn,state_val_ew; //定义state_val_sn和state_val_ew为无符号字符型变量
char code led_seg_code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //定义led_seg_code为字符型数组,初始化为0x3f、0x06、0x5b、0x4f、0x66、0x6d、0x7d、0x07、0x7f、0x6f
char code init_sn[3]={24,4,29}; //定义init_sn为字符型数组,初始化为24、4、29
char code init_ew[3]={29,24,4}; //定义init_ew为字符型数组,初始化为29、24、4
void delay(unsigned int t) //定义延时函数delay,参数为无符号整型变量t
{
while(--t); //循环t次(等待t个机器周期)
}
void led_show(unsigned int u,unsigned int v) //定义led_show函数,参数为无符号整型变量u和无符号整型变量v
{
unsigned char i; //定义i为无符号字符型变量
i=u%10; //i等于u除以10的余数
P1=led_seg_code[i]; //P1输出led_seg_code[i]
P3=0xef; //P3的最低位变为0,其余位不变
delay(50); //延时50个机器周期
P3=0xff; //P3全部位变为1
i=u%100/10; //i等于u除以10的结果的余数
P1=led_seg_code[i]; //P1输出led_seg_code[i]
P3=0xdf; //P3的第二位变为0,其余位不变
delay(50); //延时50个机器周期
P3=0xff; //P3全部位变为1
i=v%10; //i等于v除以10的余数
P2=led_seg_code[i]; //P2输出led_seg_code[i]
P3=0xbf; //P3的第三位变为0,其余位不变
delay(50); //延时50个机器周期
P3=0xff; //P3全部位变为1
i=v%100/10; //i等于v除以10的结果的余数
P2=led_seg_code[i]; //P2输出led_seg_code[i]
P3=0x7f; //P3的最高位变为0,其余位不变
delay(50); //延时50个机器周期
P3=0xff; //P3全部位变为1
}
void timer1() interrupt 3 //定时器1中断服务程序
{
T1_cnt++; //T1_cnt自加
if(T1_cnt>3999) //如果T1_cnt大于3999
{
T1_cnt=0; //T1_cnt清零
if(cnt_sn!=0) //如果cnt_sn不等于0
{
cnt_sn--; //cnt_sn自减
}
else //否则
{
state_val_sn++; //state_val_sn自加
if(state_val_sn>2)state_val_sn=0; //如果state_val_sn大于2,则state_val_sn等于0
cnt_sn=init_sn[state_val_sn]; //cnt_sn等于init_sn[state_val_sn]
if(state_val_sn==0) //如果state_val_sn等于0
{
SN_green=0; //SN_green等于0
SN_yellow=1; //SN_yellow等于1
SN_red=1; //SN_red等于1
}
else if(state_val_sn==1) //如果state_val_sn等于1
{
SN_green=1; //SN_green等于1
SN_yellow=0; //SN_yellow等于0
SN_red=1; //SN_red等于1
}
else if(state_val_sn==2) //如果state_val_sn等于2
{
SN_green=1; //SN_green等于1
SN_yellow=1; //SN_yellow等于1
SN_red=0; //SN_red等于0
}
}
if(cnt_ew!=0) //如果cnt_ew不等于0
{
cnt_ew--; //cnt_ew自减
}
else //否则
{
state_val_ew++; //state_val_ew自加
if(state_val_ew>2)state_val_ew=0; //如果state_val_ew大于2,则state_val_ew等于0
cnt_ew=init_ew[state_val_ew]; //cnt_ew等于init_ew[state_val_ew]
if(state_val_ew==0) //如果state_val_ew等于0
{
EW_green=1; //EW_green等于1
EW_yellow=1; //EW_yellow等于1
EW_red=0; //EW_red等于0
}
else if(state_val_ew==1) //如果state_val_ew等于1
{
EW_green=0; //EW_green等于0
EW_yellow=1; //EW_yellow等于1
EW_red=1; //EW_red等于1
}
else if(state_val_ew==2) //如果state_val_ew等于2
{
EW_green=1; //EW_green等于1
EW_yellow=0; //EW_yellow等于0
EW_red=1; //EW_red等于1
}
}
}
}
void button1() interrupt 0 //外部中断0服务程序
{
cnt_sn=60; //cnt_sn等于60
cnt_ew=60; //cnt_ew等于60
SN_green=1; //SN_green等于1
SN_yellow=1; //SN_yellow等于1
SN_red=0; //SN_red等于0
EW_green=1; //EW_green等于1
EW_yellow=1; //EW_yellow等于1
EW_red=0; //EW_red等于0
}
main() //主函数
{
cnt_sn=init_sn[0]; //cnt_sn等于init_sn[0]
cnt_ew=init_ew[0]; //cnt_ew等于init_ew[0]
T1_cnt=0; //T1_cnt清零
state_val_sn=0; //state_val_sn等于0
state_val_ew=0; //state_val_ew等于0
SN_green=0; //SN_green等于0
SN_yellow=1; //SN_yellow等于1
SN_red=1; //SN_red等于1
EW_green=1; //EW_green等于1
EW_yellow=1; //EW_yellow等于1
EW_red=0; //EW_red等于0
TMOD=0x20; //TMOD等于0x20
TH1=0x19; //TH1等于0x19
TL1=0x19; //TL1等于0x19
EA=1; //打开总中断
ET1=1; //打开定时器1中断
TR1=1; //启动定时器1
IT1=1; //设置外部中断1为下降沿触发
EX1=1; //打开外部中断1
IT0=1; //设置外部中断0为下降沿触发
EX0=1; //打开外部中断0
while(1) //无限循环
{
delay(10); //延时10个机器周期
led_show(cnt_sn,cnt_ew); //调用led_show函数,显示cnt_sn和cnt_ew
}
}
完善以下代码 unsigned char key_Map[] = {KEY_UP,KEY_7,KEY_8,KEY_9, KEY_Down,KEY_4,KEY_5,KEY_6, KEY_Left,KEY_1,KEY_2,KEY_3, KEY_Right,KEY_D,KEY_0,KEY_E, KEY_F1,KEY_F2,KEY_F3,KEY_F4}; //16个按键的键值数组 unsigned char key_Pressed; unsigned char key_val; unsigned char key_flag;void Check_Key(void) { unsigned char row, col; unsigned int KEY_DOUT,tmp1, tmp2; tmp1 = 0x0800; for(row=0; row<4; row++) //行扫描 { KEY_DOUT = 0X0f00; //输出全为1 KEY_DOUT-= tmp1; //依次输出一个为0 GPIOD->ODR=((GPIOD->ODR&0xf0ff)|KEY_DOUT); tmp1 >>=1; if((GPIO_ReadInputData(GPIOD)&0xf000)<0xf000) //if((KEY_DIN & 0xF0) < 0xF0) //P2输入是否有一位为0 { tmp2 = 0x1000; //用于检测出哪一位为0 for(col=0; col<4; col++) //列扫描 { if(0x00 == (GPIO_ReadInputData(GPIOD) & tmp2)) //找到等于0的列 { key_val = key_Map[row*4 + col];//获取键值 return; //退出循环 } tmp2 <<= 1; //右移1位 } } } } void KEY_Scan(void) { static u8 key_up=1;//按键按松开标志 if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)) { delay_ms(10);//去抖动 key_up=0; if(KEY1==0)key_val = key_Map[4*4 + 0];//获取键值; if(KEY2==0)key_val = key_Map[4*4 + 1];//获取键值;; if(KEY3==0)key_val = key_Map[4*4 + 2];//获取键值;; if(KEY4==0)key_val = key_Map[4*4 + 3];//获取键值;; }else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)key_up=1; } inline void Button_down(void) { KEY_Scan(); Key_Event(); }
这段代码看起来是针对单片机中的矩阵按键扫描函数。以下是一些可以改进的建议:
1. 函数名:函数名可以更加规范,建议使用大写字母和下划线的命名方式,如:CHECK_KEY、KEY_SCAN、BUTTON_DOWN。
2. 参数:函数没有参数,可以添加参数以支持更多的功能。
3. 变量名:变量名应该具有描述性,能够表达变量的含义。
4. 按键扫描:建议添加按键消抖功能,以避免按键不稳定的现象。
5. 代码风格:建议对代码进行缩进,以提高可读性。
下面是改进后的代码:
```c
typedef enum {
KEY_NONE = 0, // 无按键按下
KEY_UP,
KEY_7,
KEY_8,
KEY_9,
KEY_DOWN,
KEY_4,
KEY_5,
KEY_6,
KEY_LEFT,
KEY_1,
KEY_2,
KEY_3,
KEY_RIGHT,
KEY_D,
KEY_0,
KEY_E,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4
} KEY_Status;
/**
* @brief 获取按键状态
* @param key_map 按键映射表
* @param row 行数
* @param col 列数
* @return KEY_Status 按键状态
*/
KEY_Status get_key_status(unsigned char* key_map, unsigned char row, unsigned char col) {
return (KEY_Status)key_map[row * 4 + col];
}
/**
* @brief 矩阵按键扫描函数
* @param key_map 按键映射表
* @param mode 0:支持单次按键功能,1:支持连续按键功能
* @return KEY_Status 按键状态
*/
KEY_Status key_scan(unsigned char* key_map, u8 mode) {
static u8 key_up = 1; // 按键按松开标志
if (mode) key_up = 1; // 支持连按
unsigned char row, col;
unsigned int tmp1, tmp2, key_dout;
tmp1 = 0x0800;
for (row = 0; row < 4; row++) {
key_dout = 0x0F00;
key_dout -= tmp1;
GPIOD->ODR = ((GPIOD->ODR & 0xF0FF) | key_dout);
tmp1 >>= 1;
if ((GPIO_ReadInputData(GPIOD) & 0xF000) < 0xF000) {
tmp2 = 0x1000;
for (col = 0; col < 4; col++) {
if (0x00 == (GPIO_ReadInputData(GPIOD) & tmp2)) {
KEY_Status key_status = get_key_status(key_map, row, col);
if (key_up) {
delay_ms(10); // 去抖动
key_up = 0;
return key_status;
} else {
return KEY_NONE;
}
}
tmp2 <<= 1;
}
}
}
if (KEY_UP == get_key_status(key_map, 0, 0)) {
if (key_up) {
delay_ms(10); // 去抖动
key_up = 0;
return KEY_UP;
} else {
return KEY_NONE;
}
} else if ((KEY_7 == get_key_status(key_map, 0, 1)) && (KEY_8 == get_key_status(key_map, 0, 2)) && (KEY_9 == get_key_status(key_map, 0, 3))) {
if (key_up) {
delay_ms(10); // 去抖动
key_up = 0;
return KEY_UP;
} else {
return KEY_NONE;
}
} else {
key_up = 1;
return KEY_NONE;
}
}
/**
* @brief 按键事件处理函数
*/
void key_event(void) {
// TODO: 处理按键事件
}
/**
* @brief 按键检测函数
* @param key_map 按键映射表
* @param mode 0:支持单次按键功能,1:支持连续按键功能
*/
void check_key(unsigned char* key_map, u8 mode) {
KEY_Status key_status = key_scan(key_map, mode);
if (key_status != KEY_NONE) {
key_event();
}
}
/**
* @brief 按钮按下函数
* @param key_map 按键映射表
* @param mode 0:支持单次按键功能,1:支持连续按键功能
*/
void button_down(unsigned char* key_map, u8 mode) {
check_key(key_map, mode);
}
```
改进后的代码对函数名、参数、返回值等进行了规范化,同时添加了按键消抖功能,提高了按键扫描的稳定性。代码逻辑也更加清晰,易于阅读和维护。
阅读全文