static unsigned char GfMultBy02(unsigned char num) { if (0 == (num & 0x80)) { num = num << 1; } else { num = (num << 1) ^ BPOLY; } return num; }
时间: 2024-02-14 21:33:51 浏览: 19
这是一个计算 Galois Field (有限域)中一个数乘以 02 的函数。在有限域 GF(2^8) 中,每个数都可以表示为一个 8 位二进制数,所以这个函数的输入和输出都是一个 8 位二进制数。函数的实现方式是:如果输入二进制数的最高位为 0,则将这个数左移一位,相当于乘以 2;如果最高位为 1,则将这个数左移一位,并且将结果与多项式 BPOLY = 0x1b 进行异或运算,相当于乘以 2 并加上一个固定的数。最后返回计算结果。这个函数在 AES 加密和解密算法中有广泛应用。
相关问题
单片机,修改以下代码#include<reg52.h> unsigned char cols[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xE3,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; unsigned char p_i =0;//p_i=0表示显示第一幅图像 void main(){ //定时器1和中断 TMOD = 0x10; TR1=1; TH1=0xfc; TL1=0x67; EA=1; ET1=1; while(1); } void interrupt_T1() interrupt 3{ static unsigned char row_i=0;//row_i=0表示选中点阵第一行 static unsigned int cnt=0;//cnt=1表示进过1ms,用于点阵行的切换 static unsigned int p_cnt=0;//p_cnt=1表示进过1ms,用于图像的切换 TH1=0xfc; TL1=0x67; P0 = 0xff;//消隐 cnt++; p_cnt++; if(cnt==1){ cnt=0; row_i++; if(row_i==8){ row_i =0; } } if(p_cnt==10){ p_cnt=0; p_i++; if(p_i==17){ p_i =0; } } switch(row_i){ case 0:P2 =0x01;P0 = cols[0+p_i];break; case 1:P2=0x02;P0 = cols[1+p_i];break; case 2:P2 =0x04;P0 = cols[2+p_i];break; case 3:P2=0x08;P0 = cols[3+p_i];break; case 4:P2 =0x10;P0 = cols[4+p_i];break; case 5:P2=0x20;P0 = cols[5+p_i];break; case 6:P2 =0x40;P0 = cols[6+p_i];break; case 7:P2=0x80;P0 = cols[7+p_i];break; default:break; plaintext Copy code } }实现8*8点阵9到0倒序秒表
以下是修改后的代码:
#include<reg52.h>
unsigned char cols[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xE3,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char p_i =0;//p_i=0表示显示第一幅图像
unsigned char sec_cnt = 0; // 秒计数器
unsigned char sec_num = 9; // 当前显示的秒数
void main(){
//定时器1和中断
TMOD = 0x10;
TR1=1;
TH1=0xfc;
TL1=0x67;
EA=1;
ET1=1;
while(1);
}
void interrupt_T1() interrupt 3{
static unsigned char row_i=0;//row_i=0表示选中点阵第一行
static unsigned int cnt=0;//cnt=1表示进过1ms,用于点阵行的切换
static unsigned int p_cnt=0;//p_cnt=1表示进过1ms,用于图像的切换
TH1=0xfc;
TL1=0x67;
P0 = 0xff;//消隐
cnt++;
p_cnt++;
if(cnt==1){
cnt=0;
row_i++;
if(row_i==8){
row_i =0;
}
}
if(p_cnt==10){
p_cnt=0;
p_i++;
if(p_i==17){
p_i =0;
}
}
switch(row_i){
case 0:P2 =0x01;P0 = cols[0+p_i];break;
case 1:P2=0x02;P0 = cols[1+p_i];break;
case 2:P2 =0x04;P0 = cols[2+p_i];break;
case 3:P2=0x08;P0 = cols[3+p_i];break;
case 4:P2 =0x10;P0 = cols[4+p_i];break;
case 5:P2=0x20;P0 = cols[5+p_i];break;
case 6:P2 =0x40;P0 = cols[6+p_i];break;
case 7:P2=0x80;P0 = cols[7+p_i];break;
default:break;
}
// 每隔1秒更新秒数
if (sec_cnt == 100) {
sec_cnt = 0;
if (sec_num == 0) {
sec_num = 9;
} else {
sec_num--;
}
// 更新cols数组,显示倒序秒数
for (int i = 16; i < 24; i++) {
cols[i] = cols[i] & ~(1 << sec_num);
}
}
sec_cnt++;
}
在原有的代码基础上,我们添加了两个变量sec_cnt和sec_num,分别用于计数和记录当前秒数。在T1中断中,我们每隔1秒更新一次秒数,并更新cols数组,将倒序秒数显示在点阵上。
#include<avr/io.h> #include<avr/interrupt.h> #include <util/delay.h> #define delay_ms(x) _delay_ms(x) const unsigned char disp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f, 0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; unsigned char ledbuf[]={0x00,0x00,0x00,0x00}; unsigned int i; unsigned int sum; unsigned int y=0; int k[10]; void disp_init(void) { OCR1A = 4999; TCCR1A = 0x00; TCCR1B = (1 << WGM12); //CTC模式 TCCR1B |= (1 << CS11); //8分频 TIMSK |= (1 << OCIE1A); //开比较匹配中断A } void display(char num,char pos) { SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0); PORTB &= 0x0F; //关位选 PORTB&=~(1<<0); SPDR=num; while(0==(SPSR&0X80)); PORTB|=(1<<0); PORTB |= 1<<(7-pos); } ISR(TIMER1_COMPA_vect) { static unsigned char k=0; k=(++k)%4; display(ledbuf[k],k); PORTA=ledbuf[k]; } void io_init(void) //IO初始化 { DDRB=0xFF; PORTB=0xF8; DDRC=0xFF; PORTC&=~(1<<7); //74HC595使能 DDRD=0x00; //PORTD=0xFF;//PD口8个按键端口输入,上拉 } void get(void) { //ADMUX=(0<<REFS1)|(1<<REFS0)|(1<<MUX1); ADMUX=(1<<REFS0); ADCSRA=(1<<ADEN) |(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS0); ADCSRA|=(1<<ADSC); while(!(ADCSRA&(1<<ADIF))); ADCSRA|=(1<<ADIF); ADCSRA&=~(1<<ADEN); k[y]=ADC; y=y+1; if(y>=9) { for(y=0;y<=9;y++) { sum=k[y]+sum;} y=0; i=sum/9; sum=0; float v=i*5.0/1024; int a=(int)v; int b=(int)((v-a)*1000); ledbuf[0] = disp[a]|0x80; ledbuf[1] = disp[b/100]; ledbuf[2] = disp[(b%100)/10]; ledbuf[3] = disp[b%10]; } } void main() { io_init(); disp_init(); sei(); while (1) { get(); delay_ms(100); } }什么意思逐句解释
这是一个基于AVR单片机的程序,用来读取模拟电压并在数码管上显示其对应的数字。
1. `#include<avr/io.h>` 和 `#include<avr/interrupt.h>` 是AVR单片机编程所需的头文件。
2. `#include <util/delay.h>` 是AVR单片机编程中延时函数所需的头文件。
3. `#define delay_ms(x) _delay_ms(x)` 定义一个宏,用于延时x毫秒。
4. `const unsigned char disp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f, 0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};` 定义了一个常量数组,存储了显示0~9、A~F的数码管的段码。
5. `unsigned char ledbuf[]={0x00,0x00,0x00,0x00};` 定义了一个长度为4的字符型数组,用于存储要显示的数据。
6. `unsigned int i;` 定义了一个无符号整数型变量i。
7. `unsigned int sum;` 定义了一个无符号整数型变量sum。
8. `unsigned int y=0;` 定义了一个无符号整数型变量y,并初始化为0。
9. `int k[10];` 定义了一个长度为10的整型数组k,用于存储读取到的10个模拟量数据。
10. `void disp_init(void)` 定义了一个名为disp_init的函数,用于初始化计时器1,以实现数码管的定时扫描。
11. `void display(char num,char pos)` 定义了一个名为display的函数,用于控制74HC595芯片输出数字和位选信号,实现数码管的显示。
12. `ISR(TIMER1_COMPA_vect)` 是定时器1比较匹配中断服务程序,用于定时扫描数码管并显示数码管上的数字。
13. `void io_init(void)` 定义了一个名为io_init的函数,用于初始化IO口,包括74HC595芯片和按键等。
14. `void get(void)` 定义了一个名为get的函数,用于读取模拟电压,并将其转换为数字并显示在数码管上。
15. `void main()` 是程序主函数。
16. `io_init();` 调用io_init函数,初始化IO口。
17. `disp_init();` 调用disp_init函数,初始化计时器1,以实现数码管的定时扫描。
18. `sei();` 开启全局中断。
19. `while (1) { get(); delay_ms(100); }` 无限循环,不断读取模拟电压并显示在数码管上,每次循环延时100毫秒。