代替 count(*) 的更有效率的办法

部署运行你感兴趣的模型镜像
 对于SQL server用户,有一个比SQL标准的count(*)更节省资源的获取表中纪录数的方法。可以从sysindexes表中获得值,SQL server自动地将最新的纪录数保存在这个表中。实现这个任务的SQL查询的语法如下:
    
    SELECT rows FROM sysindexes WHERE id=OBJECT_ID ('your_table')  

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

void Compute_Voltage(void) { uint8 i,j; float temp_rms[3] = {0.0,0.0,0.0}; // float diff, delta; for(j=0; j<3; j++) { uart_com_unpack(); for(i=0; i<sample_num; i++) { temp_ad_val[i] = adc_val[j][i]; } ad_average[j] = Average_Precess(&temp_ad_val,sample_num); temp_rms[j] = RMS_Process(&temp_ad_val,sample_num,ad_average[j]); //memset(temp_ad_val,0,100*sizeof(uint16)); if(fabs(temp_rms[j] - ad_rms[j]) <= 50.0f) { ad_rms[j] = 0.02f*temp_rms[j] + 0.98f*ad_rms[j]; } else if(fabs(temp_rms[j] - ad_rms[j]) <= 100.0f) { ad_rms[j] = 0.03f*temp_rms[j] + 0.97f*ad_rms[j]; } else if(fabs(temp_rms[j] - ad_rms[j]) <= 150.0f) { ad_rms[j] = 0.05f*temp_rms[j] + 0.95f*ad_rms[j]; } else { ad_rms[j] = temp_rms[j]; } } //*******************************************// //***********这里预留一个量程****************// //*******************************************// for(i=0; i<3; i++) //用for循环可以节省flash 后面可以合并 { uart_com_unpack(); // 在电压计算循环中加入: if(calibration_lock[i]) { // 校准锁定模式下,在±2V范围内保持锁定 if(fabs(temp_voltage[i] - modbus_rx_data) < 5.0f) { Voltage[i] = modbus_rx_data; } else { calibration_lock[i] = 0; // 超出范围解除锁定 } } else{ temp_voltage[i] = (float)(ad_rms[i]*1000.0f/base_info.V_K[i]); if(temp_voltage[i] <=30.0f) //小于2V清零 Voltage[i] = 0.0f; else { if(((temp_voltage[i] - Voltage[i]) > -20.0f) && ((temp_voltage[i] - Voltage[i]) < 20.0f)) { Voltage[i] = 0.02f*temp_voltage[i] + 0.98f*Voltage[i]; } else if(((temp_voltage[i] - Voltage[i]) > -50.0f) && ((temp_voltage[i] - Voltage[i]) < 50.0f)) { Voltage[i] = 0.03f*temp_voltage[i] + 0.97f*Voltage[i]; } else if(((temp_voltage[i] - Voltage[i]) > -100.0f) && ((temp_voltage[i] - Voltage[i]) < 100.0f)) { Voltage[i] = 0.04f*temp_voltage[i] + 0.96f*Voltage[i]; } else if(((temp_voltage[i] - Voltage[i]) > -150.0f) && ((temp_voltage[i] - Voltage[i]) < 150.0f)) { Voltage[i] = 0.05f*temp_voltage[i] + 0.95f*Voltage[i]; } else { Voltage[i] = temp_voltage[i]; } } } } } void main(void) { sys_init(); while(1) { WT_init(); Compute_Voltage(); if(0 == compute_flag) { Compute_Current(); if(1 == freq_start_flag) //当串口调整PWM时,不进行采样频率切换 { Freq = (float)((10000.0f/int0_time_50)+0.5f)*100.0f; // 1000/(time*5/100) *100 //Freq = (1000.0f/(int0_time_50*5.0f/INT_NUM)) *100.0f; change_sample_freq(); freq_start_flag =0; //计算完毕,等待下一次计算采样频率 T_cpmpute_flag = 0; //外部中断重新开始计数 int0_time_50 = 0; //计时时间清零 } } uart_com_unpack(); } }uint16 Int0_count = 0; //进入外部中断的次数,初始化为0 void io_init(void) { /********************************* 1 输出 0 输入 ************************************* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 端口控制寄存器 P0CR : P0CR.7 P0CR.6 - - P0CR.3 - - - P1CR : - - - P1CR.4 P1CR.3 P1CR.2 P1CR.1 P1CR.0 P2CR : - - - - - - P2CR.1 P2CR.0 P3CR : P3CR.7 P3CR.6 P3CR.5 P3CR.4 P3CR.3 P3CR.2 P3CR.1 P3CR.0 P4CR : - - - P4CR.4 P4CR.3 P4CR.2 P4CR.1 P4CR.0 P5CR : - - - - - P5CR.2 P5CR.1 P5CR.0 端口上拉电阻控制寄存器 PxPCRy 寄存器位有效同上 0:内部上拉电阻关闭 1:内部上拉电阻开启 *******************************************************************************************/ P0CR = 0x08; //P03 LED P2CR = 0x02; //P20(RXD) P21(TXD) P3CR = 0x0E; P2_0 =0; P2_1 = 1; P3_1 = 1; P3_2 = 1; P0_3 = 1; LED_ON(); } void INT2_config(void) { EXF0 &= 0xF3; _nop_(); //清空bit3 bit2 EXF0 |= 0x04; //P06下降沿触发 EXF0 &= 0xfe; //清中断2标志位 IEN1 |= 0x02; //使能外部中断2 } /******************************************************************** 外部中断2 中断处理(中断入口地址 = 8) 下降沿中断 P0_6 ********************************************************************/ void ISR_INT2(void) interrupt 8 { if(0 ==T_cpmpute_flag) //当标志位为清0 时后,才开始自加 { Int0_count++; if(Int0_count >= INT_NUM) { Int0_count = 0; T_cpmpute_flag = 1; } } } void uart_command_process(void) { modbus_register_addr = (uart_rx_buf[2] <<8) | uart_rx_buf[3]; modbus_rx_data = (uart_rx_buf[4] <<8) | uart_rx_buf[5]; if(modbus_command == 0x03) { if((modbus_register_addr >=1) &&((modbus_register_addr + modbus_rx_data-1)<=21)) { Return_03(modbus_register_addr -1); } } else if(modbus_command == 0x06) { switch(modbus_register_addr) { case 0x201 :{ //第一路电压/电流校正 Input_Calibration(0); break; } case 0x202 :{ //第二路电压/电流校正 Input_Calibration(1); break; } case 0x203 :{ //第三路电压/电流校正 Input_Calibration(2); break; } case 0x0004 :{ //修改地址 if((modbus_rx_data >= check_parameter_rang[1][0]) || (modbus_rx_data <= check_parameter_rang[1][2])) { base_info.product_add = modbus_rx_data; } else { Return_error_flag = 1; } break; } case 0x000F :{ //修改量程 if((modbus_rx_data >= check_parameter_rang[2][0]) || (modbus_rx_data <= check_parameter_rang[2][2])) { base_info.range = modbus_rx_data; } else { Return_error_flag = 1; } break; } case 0x1002 :{ //修改1路4mA save_count[0] += modbus_rx_data; if(save_count[0] < 10) save_count[0] = 10; //防止溢出 else if(save_count[0] > 4094) save_count[0] = 4084; PWM_Change_Duty(save_count[0]); compute_flag = 1; break; } case 0x1003 :{ //修改1路20mA save_count[1] += modbus_rx_data; if(save_count[1] < 10) save_count[1] = 10; //防止溢出 else if(save_count[1] > 4094) save_count[1] = 4084; PWM_Change_Duty(save_count[1]); compute_flag = 1; break; } case 0x1004 :{ //保存1路校准值 base_info.PWM1_4mA = save_count[0]; //保存的都是高电平的时间 base_info.PWM1_20mA = save_count[1]; compute_flag = 0; break; } case 0x1005 :{ //修改2路4mA save_count[2] += modbus_rx_data; if(save_count[2] < 1000) save_count[2] = 1000; //防止溢出 else if(save_count[2] > 36000) save_count[2] = 36000; Count_TH4 = save_count[2]; compute_flag = 1; break; } case 0x1006 :{ //修改2路20mA save_count[3] += modbus_rx_data; if(save_count[3] < 1000) save_count[3] = 1000; else if(save_count[3] > 36000) save_count[3] = 36000; Count_TH4 = save_count[3]; compute_flag = 1; break; } case 0x1007 :{ //保存2路校准值 base_info.PWM2_4mA = save_count[2]; //保存的都是高电平的时间 base_info.PWM2_20mA = save_count[3]; compute_flag = 0; break; } case 0x1008 :{ //修改3路4mA save_count[4] += modbus_rx_data; if(save_count[4] < 1000) save_count[4] = 1000; else if(save_count[4] > 36000) save_count[4] = 36000; Count_TH5 = save_count[4]; compute_flag = 1; break; } case 0x1009 :{ //修改3路20mA save_count[5] += modbus_rx_data; if(save_count[5] < 1000) save_count[5] = 1000; else if(save_count[5] > 36000) save_count[5] = 36000; Count_TH5 = save_count[5]; compute_flag = 1; break; } case 0x1010 :{ //保存3路校准值 base_info.PWM3_4mA = save_count[4]; //保存的都是高电平的时间 base_info.PWM3_20mA = save_count[5]; compute_flag = 0; break; } case 0x1011 :{ //3路校准值统一保存 base_info.PWM1_4mA = save_count[0]; //保存的都是高电平的时间 base_info.PWM1_20mA = save_count[1]; base_info.PWM2_4mA = save_count[2]; //保存的都是高电平的时间 base_info.PWM2_20mA = save_count[3]; base_info.PWM3_4mA = save_count[4]; //保存的都是高电平的时间 base_info.PWM3_20mA = save_count[5]; compute_flag = 0; break; } } if((modbus_register_addr != 0x1002) || (modbus_register_addr != 0x1003) || (modbus_register_addr != 0x1005) || (modbus_register_addr != 0x1006) \ || (modbus_register_addr != 0x1008) || (modbus_register_addr != 0x1009)) { DataFlsh_U16_Write(); } if(0 == Return_error_flag) Return_Frame(modbus_rx_data); else Return_error_flag = 0; //重新清零 避免下一次不返回 LED_TOGGLE(); } } void uart_com_unpack(void) { uint8 i; if(1 == uart_rx_finish_ifg) { modbus_command = Frame_CRC16(uart_rx_buf); if(modbus_command != 0) { uart_command_process(); } for(i=0; i<10; i++) { uart_rx_buf[i] = 0; uart_rx_finish_ifg = 0; uart_rx_count = 0; } } } void UART0_config(void) { SCON = 0x40; //EUART0控制及状态寄存器 //bit[7:6]:SM[0:1] EUART0串行方式控制位, SSTAT = 0 // 00:方式0,同步方式,固定波特率 // 01:方式1, 8位异步方式,可变波特率 // 10:方式2, 9位异步方式,固定波特率 // 11:方式3, 9位异步方式,可变波特率 //bit5 :SM2 EUART0多处理机通讯允许位(第9位“1”校验器), SSTAT = 0 // 0:在方式0下,波特率是系统时钟的1/12 // 在方式1下,禁止停止位确认检验,停止位将置RI为1产生中断 // 在方式2和3下,任何字节都会置RI为1产生中断 // 1:在方式0下,波特率是系统时钟的1/4 // 在方式1下,允许停止位确认检验,只有有效的停止位(1)才能置RI为1产生中断 // 在方式2和3下,只有寻址字节(第9位 = 1)能置RI为1产生中断 //bit4 :REN EUART0接收器允许位 // 0:接收禁 // 1:接收允许 //bit3 :TB8 在EUART0的方式2和3下发送的第9位,由软件置1或清0 //bit2 :RB8 在EUART0的方式1, 2和3下接收的第9位 // 在方式0下,不使用RB8 // 在方式1下,如果接收中断发生, RB8的停止位会收到信号 // 在方式2和3下,由第9位接收 //bit1 :TI EUART0的传送中断标志位 // 0:由软件清0 // 1:由硬件置1,在方式0下的第8位最后,或在其它方式下的停止位开始 //bit0 :RI EUART0的接收中断标志位 // 0:由软件清0 // 1:由硬件置1,在方式0下的第8位最后,或在其它方式下的停止位开始 //SBUF //EUART0数据寄存器:写入将发送字节到移位寄存器中,然后开始传输;读取返回接收锁存器中的内容 PCON = 0x00; //电源控制寄存器 //bit7 :SMOD 波特率加倍器 // 在方式1和3中, SMOD = 1,若使用定时器4作为波特率发生器,波特率加倍(仅适用EUAT0) // 在方式2中, SMOD = 1,波特率加倍( EUART0和EUART1都适用) //bit6 :SSTAT SCON[7:5]功能选择位 // 0: SCON[7:5]工作方式作为SM0, SM1, SM2 // 1: SCON[7:5]工作方式作为FE, RXOV, TXCOL //bit5 :SSTAT1 SCON1[7:5]功能选择位 // 0: SCON1[7:5]工作方式作为SM10, SM11, SM12 // 1: SCON1[7:5]工作方式作为FE1, RXOV1, TXCOL1 //bit4 :- //bit[3:2]:GF[1:0] 用于软件的通用标志 //bit1 :PD 掉电模式控制位 // 0:当一个中断或复位产生时由硬件清0 // 1:由软件置1激活掉电模式 //bit0 :IDL 空闲模式控制位 // 0:当一个中断或复位产生时由硬件清0 // 1:由软件置1激活空闲模式 IEN0 |= (0x10); //bit4: 1(允许串口0中断) //EA EADC ET2 ES0 - - ET5 - } /*************定时器2 波特率发生器********************/ void Timer2_config(void) { T2CON = 0x30; //停止定时器2 // bit0: 0 此位写0 // bit1:0 此位写0 // bit2:0 停止定时器2 // 1 开始定时器2 // bit3:0 此位写0 // bit4:TCLK EUART0发送时钟控制位 // 0 定时器4产生发送波特率 // 1 定时器2产生发送波特率 // bit5:RCLK EUART0接收时钟控制位 // 0 定时器4产生接收波特率 // 1 定时器2产生接收波特率 // bit6:0 此位写0 // bit7:0 无溢出(必须由软件清0) // TF2 1 溢出(如果RCLK = 0和TCLK = 0,由硬件设1) T2MOD = 0x00; // bit0:0 此位写0 // bit1:0 此位写0 // bit[7:2]:- RCAP2H = (uint8)((0xFFD9)>>8); //9600 RCAP2L = (uint8)((0xFFD9)&0xff); TL2 = RCAP2L; TH2 = RCAP2H; /* BaudRate = (1 / (2 * 16)) * fsys / (65536 - [RCAP2H、RCAP2L]) */ IEN0 &= 0xdf; //bit5: 1(禁止定时器2溢出中断) //EA EADC ET2 ES0 - - ET5 - } void UART0_Start(void) { T2CON |= (0x04); //bit2: 1(启动定时器2) SCON |= 0x10; //默认允许接收 } void URART0_Init(void) //注意串口初始化顺序 { Timer2_config(); UART0_config(); UART0_Start(); } void UART0_Tx(uint8* tx_p,uint8 len) { com_err_time =0; //60秒超时判断清零 REN = 0; //禁止接收 uart_tx_buf_p =tx_p; SBUF =uart_tx_buf_p[0]; uart_tx_ptr =1; uart_tx_count =len-1; } /******************************************************************** 串口0中断处理(中断入口地址 = 4) 发送完成后允许接收 ********************************************************************/ void ISR_Uart0(void) interrupt 4 { if(TI == 1) { TI = 0; if(uart_tx_count) { SBUF = uart_tx_buf_p[uart_tx_ptr]; uart_tx_ptr++; uart_tx_count--; } else { REN = 1; //允许接收 } } if(RI == 1) { RI = 0; uart_rx_buf[uart_rx_count]=SBUF; if(uart_rx_count==0) { if(uart_rx_buf[0]== base_info.product_add || uart_rx_buf[0]==0xFA) { uart_rx_count++; uart_start_time(); } } else { if(uart_rx_buf[1]==0x03 || uart_rx_buf[1]==0x06) { uart_rx_count++; uart_start_time(); } else { uart_rx_count=0; } } if(uart_rx_count>=10) { uart_rx_count=9; } } }//CRC校验子程序 uint16 CRC16(uint8 *crcdata,uint16 length) { uint8 jj=0,crch=0xff,crcl=0xff,flag=0; uint16 ii=0; for(ii=0;ii<length;ii++) { crcl^=*(crcdata+ii); for(jj=0;jj<8;jj++) { flag=crcl&0x01; crcl=(crcl>>1)+(crch&0x01)*0x80; crch>>=1; if(flag!=0) { crcl^=0x01; crch^=0xa0; } } } return(crcl*256+crch); }xdata uint16 time3_led_count = 0; /******************************************************************** 中断优先级改变函数 isp_num 对应中断的中断号 leve 设置的中断优先级 0最低 3最高 ********************************************************************/ void isp_priority(uint8 isp_num,uint8 leve) { uint8 group; group = isp_num % 7; if (isp_num >= 8) { IPL1 &= ~((0x01) << group); IPH1 &= ~((0x01) << group); IPL1 |= ((leve&0x01)<<group); IPH1 |= (((leve>>1)&0x01)<<group); } else { IPL0 &= ~((0x01) << group); IPH0 &= ~((0x01) << group); IPL0 |= ((leve&0x01)<<group); IPH0 |= (((leve>>1)&0x01)<<group); } } //晶振时钟初始化 时钟主要有代码选项决定 void clock_init(void) { CLKCON = 0x00; //设置系统时钟不分频 fSYS = fOSCS = 12MHz } //1S看门狗复位 初始化相当于喂狗 void WT_init(void) { RSTSTAT=0x01; //看门狗1024mS 可以通过代码选项配置 } void Timer3_Start(void) { INSCON = 0x40; T3CON |= (0x04); //bit2: 1(启动定时器3) INSCON = 0x00; } /*************定时器3 自动重装载定时器*******用作adc、串口解包、LED*************/ void Timer3_config(void) { INSCON = 0x40; T3CON = 0x00; //停止定时器3 // bit[1:0]: 定时器3定时器/计数器方式选定位 // 00:系统时钟 // 01:保留 // 10:外部32.768kHz晶体谐振器或Internal 128k RC // 11:保留 // bit2 : TR3 定时器3允许控制位 // 0: 停止定时器3 // 1: 开始定时器3 // bit3 :- // bit[5:4]: 定时器3预分频比选择位 // 00:1/1 // 01:1/8 // 10:1/64 // 11:1/256 // bit6 :- // bit7 :TF3 定时器3溢出标志位 // 0: 无溢出(硬件清0) // 1: 溢出(由硬件设1) //选用系统时钟作为定时器时钟、不分频 TL3 = (uint8)((65535-4800)&0xff); //4800 TH3 = (uint8)((65535-4800)>>8); SWTHL = 0x00; // // bit0 : T3HLCON // 0:读TH3和TL3时,返回值为T3计数器值 // 1:读TH3和TL3时,返回值为T3重载寄存器值 // bit1 :T5HLCON // 0:读TH5和TL5时,返回值为T5计数器值 // 1:读TH5和TL5时,返回值为T5重载寄存器值 // bit[7:2]:- INSCON = 0x00; IEN1 |= 0x10; //bit4: 1(允许定时器3中断) //ESCM/ELPD/CRC ET4 EPWM ET3 EX4 EX3 EX2 - IENC1 |= 0x10; //bit4: 1(允许定时器3中断) //- ECRC - ET3 - - ESCM ELPD Timer3_Start(); } void Timer4_Start(void) { INSCON = 0x40; T4CON |= (0x02); //bit1: 1(启动定时器4) INSCON = 0x00; } /*************定时器4 自动重装载定时器***********************************/ void Timer4_config(void) { INSCON = 0x40; T4CON = 0x00; //定时器4控制寄存器,禁止定时器4 // bit0 :T4CLKS 定时器4时钟源选择位 // 0: 系统时钟, T4端口作为I/O口 // 1: T4端口输入外部时钟,自动上拉 // bit1 :TR4 定时器4允许控制位 // 0: 禁止定时器4 // 1: 允许定时器4 // bit[3:2] : T4M[1:0] 定时器4方式选择位 // 00: Mode0, 16位自动重载定时器 // 01: Mode1, EUART波特率发生器 // 10: Mode2, T4端口上升沿触发(只用系统时钟, T4CLKS无效) // 11: Mode2, T4端口下降沿触发(只用系统时钟, T4CLKS无效) // bit[5:4] : T4PS[1:0] 定时器4预分频比选择位 // 00: 1/1 // 01: 1/8 // 10: 1/64 // 11: 1/256 // bit6 :TC4 比较功能允许位 // 当T4M[1:0] = 00 // 0: 禁止定时器4比较功能 // 1: 允许定时器4比较功能 // 当T4M[1:0] = 10或11 // 0: 定时器4不能被再触发 // 1: 定时器4可以被再触发 // bit7 :TF4 定时器4溢出标志位 // 0: 无溢出(硬件清0) // 1: 溢出(由硬件设1) TL4 = (uint8)((65535-4333)&0xff); //30000 TH4 = (uint8)((65535-4333)>>8); INSCON = 0x00; IEN1 |= 0x40; //bit6: 1(允许定时器4中断) //ESCM/ELPD/CRC ET4 EPWM ET3 EX4 EX3 EX2 - Timer4_Start(); } void Timer5_Start(void) { INSCON = 0x40; T5CON |= (0x02); //bit1: 1(启动定时器5) INSCON = 0x00; } /*************定时器5 自动重装载定时器*******用作IO模拟PWM*************/ void Timer5_config(void) { INSCON = 0x40; T5CON = 0x00; //停止定时器5 // bit0 :- // bit1 : 定时器5定时器/计数器方式选定位 // 0: 停止定时器5 // 1: 开始定时器5 // bit[3:2]:- // bit[5:4]: T5PS[1:0] 定时器5预分频比选择位 // 00:1/1 // 01:1/8 // 10:1/64 // 11:1/256 // bit6 :- // bit7 :TF5 定时器5溢出标志位 // 0: 无溢出(硬件清0) // 1: 溢出(由硬件设1) //选用系统时钟作为定时器时钟、不分频 TL5 = (uint8)((65535-4338)&0xff); // 30000 TH5 = (uint8)((65535-4338)>>8); SWTHL = 0x00; // // bit0 : T3HLCON // 0:读TH3和TL3时,返回值为T3计数器值 // 1:读TH3和TL3时,返回值为T3重载寄存器值 // bit1 :T5HLCON // 0:读TH5和TL5时,返回值为T5计数器值 // 1:读TH5和TL5时,返回值为T5重载寄存器值 // bit[7:2]:- INSCON = 0x00; IEN0 |= 0x02; //bit1: 1(允许定时器5溢出中断) //EA EADC ET2 ES0 - - ET5 - Timer5_Start(); } void PWM_Start(void) { PWMLO = 0x55; PWMEN = 0x81; //允许PWM模块 PWMLO = 0x00; } void PWM1_config(void) { PWMLO = 0x55; //只有此位写0x55、才可以改其他PWM寄存器 PWM0C = 0x03; //12位PWM控制寄存器 // bit[1:0]: TnCK0[1:0] 12位PWM时钟源选择位(与TnCK02配合控制) // 000:振荡器时钟/2 // 001:振荡器时钟/4 // 010:振荡器时钟/8 // 011:振荡器时钟/16 // 100:振荡器时钟/1 // 101:振荡器时钟/32 // 110:振荡器时钟/64 // 111:振荡器时钟/256 // bit2 : PWM0S PWM0输出模式 // 0: 高电平驱动, PWM占空比期间输出高电平,占空比溢出后输出低电平 // 1: 低电平驱动, PWM占空比期间输出低电平,占空比溢出后输出高电平 // bit[4:3]: - FLTS FLTC // bit5 : TnCK02 12位PWM时钟源选择位(与TnCK0[1:0]配合控制) // 参见TnCK0[1:0]描述 // bit6 : PWM0IF PWM0中断标志位 // 0: 软件清零0 // 1: 硬件置1, PWM0周期计数器溢出 // bit7 :PWM0IE PWM0中断允许位(当IEN1寄存器中的EPWM位置1) // 0: 禁止PWM0中断 // 1: 允许PWM0中断 PWM0PL = (uint8)(0x0ffe & 0xff); // PWM周期控制寄存器 PWM输出周期 = PWMP * PWM时钟 PWM0PH = (uint8)(0x0ffe >> 8); PWM0DL = (uint8)(0x144 & 0xff); // PWM占空比控制寄存器 0x07ff PWM0DH = (uint8)(0x144 >> 8); PWMEN = 0x00; //PWM定时器允许寄存器 //bit0 : PWM0OE 12位PWM输出端口PWM0x使能位 // 0: PWM0输出禁止,用作I/O功能 // 1: PWM0模块使能, PWM0输出允许 //bit[5:1] : - //bit6 : EFLT FLT引脚配置位 // 0: 普通I/O端口或S\S\引脚 // 1: PWM故障检测输入引脚 //bit7 : EPWM0 12位PWM0输出控制位 // 0: PWM0输出禁止,用作I/O功能 // 1: PWM0输出允许 PWMLO = 0xAA; //保护功能打开、不允许写PWM寄存器 PWM_Start(); } void PWM_Change_Duty(uint16 duty) { PWMLO = 0x55; PWM0DL = (uint8)(duty & 0xff); // PWM占空比控制寄存器 PWM0DH = (uint8)(duty >> 8); PWMLO = 0xAA; } /****************************************************************************** 定时器3中断处理(中断入口地址 = 11) 400us定时器 会实时改变(334us-500us) 指示灯闪烁和串口解包时间并不一定是准确的,但是不影响 ******************************************************************************/ xdata uint16 adc_count =0; void ISR_Timer3(void) interrupt 11 { INSCON = 0x40; T3CON &= 0x7f; INSCON = 0x00; /*****************ADC获取*************************/ adc_val[0][adc_count] = adctemp[0]; adc_val[1][adc_count] = adctemp[1]; adc_val[2][adc_count] = adctemp[2]; adc_count++; if(adc_count >= sample_num) { adc_count=0; //if(0 == change_sample_freq_flag) //变换频率小于1Hz不调整采样时间 //{ INSCON = 0x40; TL3 = (uint8)((65535-Count_TH3)&0xff); //放在这里,确保是一次完整的buf值转换后再改变周期 TH3 = (uint8)((65535-Count_TH3)>>8); INSCON = 0x00; //} } /*****************UART解包*************************/ uart_rx_finish_check(); /*****************LED状态*************************/ time3_led_count++; if(com_err_time<60000&&(time3_led_count%2==1)) com_err_time++; if(com_err_time>=60000) { if(time3_led_count%400==0) //5HZ { LED_ON(); } else if(time3_led_count%400==200) { LED_OFF(); } } else { if(time3_led_count%2000==0) //1HZ { LED_ON(); } else if(time3_led_count%2000==1000) { LED_OFF(); } } /*****************END*************************/ } /******************************************************************** 定时器4中断处理(中断入口地址 = 13) 总5ms定时器 初始 TH =2500 bit freq_start_flag =0 初始值,代表未开始计算频率 =1 代表开始计算频率() T_cpmpute_flag =0 初始默认值 此时在外部中断中计数,同时代表频率计算完成,恢复为0,外部中断继续计数 =1 此时代表外部中断50次计数完成,开始在定时器4赋值 =2 代表赋值成功 ********************************************************************/ bit time4_pwm_flag = 0; bit freq_start_flag = 0; xdata uint8 T_cpmpute_flag = 0; xdata uint16 Count_TH4 = 4333; xdata uint16 int0_time = 0; xdata float int0_time_50 = 0; xdata float temp_Hz = 5.0f; //后期确定计算后可删除 void ISR_Timer4(void) interrupt 13 { INSCON = 0x40; T4CON &= 0x7f; INSCON = 0x00; if(0 == time4_pwm_flag) //代表周期内高电平时间到 { P3_2 = 0; time4_pwm_flag = 1; INSCON = 0x40; TL4 = (uint8)((5535+Count_TH4)&0xff); //此时是显示低电平的时间 TH4 = (uint8)((5535+Count_TH4)>>8); INSCON = 0x00; } else if(1 == time4_pwm_flag) //代表周期内低电平时间到 一个周期完成 { P3_2 = 1; time4_pwm_flag = 0; INSCON = 0x40; TL4 = (uint8)((65535-Count_TH4)&0xff); //此时是显示高电平的时间 TH4 = (uint8)((65535-Count_TH4)>>8); INSCON = 0x00; if(Int0_count >0) { int0_time++; } if(1 == T_cpmpute_flag) //代表外部中断已经中断了50次 { int0_time_50 = int0_time + temp_Hz; //在此处加5,由于主函数中计算优化,这里加5代表加上5ms,会使计算频率稍微准确 9 freq_start_flag = 1; //代表此时可以在主循环中计算频率以及改变采集周期了 T_cpmpute_flag = 2; //此时不允许外部中断计数 int0_time =0; } } } /******************************************************************** 定时器5中断处理(中断入口地址 = 1) 总5ms定时器 ********************************************************************/ bit time5_pwm_flag = 0; xdata uint16 Count_TH5 = 4338; void ISR_Timer5(void) interrupt 0x01 { INSCON = 0x40; T5CON &= 0x7f; INSCON = 0x00; if(0 == time5_pwm_flag) { P3_1 = 0; time5_pwm_flag = 1; INSCON = 0x40; TL5 = (uint8)((5535+Count_TH5)&0xff); //此时是显示低电平的时间 TH5 = (uint8)((5535+Count_TH5)>>8); INSCON = 0x00; } else if(1 == time5_pwm_flag) { P3_1 = 1; time5_pwm_flag =0; INSCON = 0x40; TL5 = (uint8)((65535-Count_TH5)&0xff); //此时是显示高电平的时间 TH5 = (uint8)((65535-Count_TH5)>>8); INSCON = 0x00; } } //uart 开启超时判断 void uart_start_time(void) { uart_rx_time_start=1; uart_rx_over_time=10; } //uart 接收判断 void uart_rx_finish_check(void) { if(uart_rx_time_start==1) { if(uart_rx_over_time>0) { uart_rx_over_time--; } else { uart_rx_finish_ifg=1; uart_rx_time_start=0; } } } //帧数据处理,若数据帧正确,则返回命令值 uint8 Frame_CRC16(uint8 *data_p) { uint8 Command_temp; uint16 CRCtemp=0; uint16 CRCdata=0; if(data_p[1]==0x03||data_p[1]==0x06) { CRCdata = CRC16(data_p,6); CRCtemp=data_p[6]; CRCtemp <<=8; CRCtemp |= data_p[7]; if(CRCdata==CRCtemp) { Command_temp = data_p[1]; return Command_temp; } } return 0; } //校验命令返回值 void Return_Frame(uint16 dt) { uint16 CRC_temp = 0; uart_tx_buf[0]=uart_rx_buf[0]; uart_tx_buf[1]=uart_rx_buf[1]; uart_tx_buf[2]=uart_rx_buf[2]; uart_tx_buf[3]=uart_rx_buf[3]; uart_tx_buf[5]=dt; //电压低八位 uart_tx_buf[4]=dt>>8; //电压高八位 CRC_temp = CRC16(uart_tx_buf,6); uart_tx_buf[7]=CRC_temp; uart_tx_buf[6]=CRC_temp>>8; UART0_Tx(uart_tx_buf,8); } modbuspoll挂机测通讯的话10000次存在11次通讯错误怎么软件修改让通讯稳定crc校验不使用查表法
08-15
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值