Вс май 09, 2021 06:49:45
Вс май 09, 2021 08:51:44
34: 97 fd sbrc r25, 7
36: 01 96 adiw r24, 0x01 ; 1
Вс май 09, 2021 22:48:58
Вот без последующего сложенияlizard66 писал(а):PS: Однако, с последующим сложением это равнозначно предварительному переводу в дополнительный код, и результат верный
volatile uint8_t temp;
temp = -20; (0xEC)
temp = ((int8_t)(temp)/ 2); работает
38: 80 91 00 00 lds r24, 0x0000 ; 0x800000 <__SREG__+0x7fffc1>
3c: 87 fd sbrc r24, 7
3e: 8f 5f subi r24, 0xFF ; 255
40: 85 95 asr r24
42: 80 93 00 00 sts 0x0000, r24 ; 0x800000 <__SREG__+0x7fffc1>
temp = ((temp)/ 2); не работает
38: 80 91 00 00 lds r24, 0x0000 ; 0x800000 <__SREG__+0x7fffc1>
3c: 86 95 lsr r24
3e: 80 93 00 00 sts 0x0000, r24 ; 0x800000 <__SREG__+0x7fffc1>
temp = ((int8_t)(temp)>>1); работает
38: 80 91 00 00 lds r24, 0x0000 ; 0x800000 <__SREG__+0x7fffc1>
3c: 85 95 asr r24
3e: 80 93 00 00 sts 0x0000, r24 ; 0x800000 <__SREG__+0x7fffc1>
temp = ((temp)>>1); не работает
38: 80 91 00 00 lds r24, 0x0000 ; 0x800000 <__SREG__+0x7fffc1>
3c: 86 95 lsr r24
3e: 80 93 00 00 sts 0x0000, r24 ; 0x800000 <__SREG__+0x7fffc1>
Пн май 10, 2021 00:05:20
у и как эта твоя фигня работает?Dimon456 писал(а):temp = ((int8_t)(temp)/ 2); работает
Пн май 10, 2021 07:32:01
В чем проблема? Вы по чему мне это приписали?Starichok51 писал(а):у и как эта твоя фигня работает?
Out_To_Display += (ADC - Out_To_Display) / 2;
Пн май 10, 2021 09:28:38
Пн май 10, 2021 09:32:59
Пн май 10, 2021 09:40:41
volatile uint8_t temp;
temp = -20; (0xEC)
Вт май 11, 2021 20:43:39
Ср май 12, 2021 20:32:41
Ср июл 28, 2021 10:12:55
Чт ноя 09, 2023 11:58:38
//кодировка для 3-х разрядного va-метра //ATmega_8A + max7219 //va-meter +0...99.9v / +0...35a (10bit/10bit)
//16MHz
//Other Linker Flafs: -Wl,-u,vfprintf -lprintf_flt -lm (активизация режима вычислений с плавающей точкой)
#define F_CPU 16000000UL //тактовая частота мк (unsigned long)
#include <avr/io.h> //подключение библиотеки "ввод/вывод" мк
#include <util/delay.h> //подключение библиотеки "пауза" мк
#include <avr/interrupt.h> //подключение библиотеки "прерывание" мк
#define Vref 4.096 //+Vref=4.096vdc
#define Kv 4.194 //коэффициент преобразования для вычислнения величины [V] Kv=1023*4.096/999
#define Ki 11.197 //коэффициент преобразования для вычислнения величины [I] Ki=1023*4.096/350
#define ADC_CS0_0 PORTB &= ~(1<<PORTB0) //ADC_CS0=0
#define ADC_CS0_1 PORTB |= (1<<PORTB0) //ADC_CS0=1
#define ADC_CS1_0 PORTB &= ~(1<<PORTB2) //ADC_CS1=0
#define ADC_CS1_1 PORTB |= (1<<PORTB2) //ADC_CS1=1
#define ADC_CLK_0 PORTB &= ~(1<<PORTB5) //ADC_CLK=0
#define ADC_CLK_1 PORTB |= (1<<PORTB5) //ADC_CLK=1
#define DRV_CLK_0 PORTC &= ~(1<<PORTC0) //DRV_CLK=0
#define DRV_CLK_1 PORTC |= (1<<PORTC0) //DRV_CLK=1
#define DRV_CS_0 PORTC &= ~(1<<PORTC1) //DRV_CS=0
#define DRV_CS_1 PORTC |= (1<<PORTC1) //DRV_CS=1
#define DRV_DT_0 PORTC &= ~(1<<PORTC2) //DRV_DT=0
#define DRV_DT_1 PORTC |= (1<<PORTC2) //DRV_DT=1
//----------
unsigned int Digit[8]; //массив переменных Digit (8 разрядов led-драйвера)
unsigned char dt_in[8]; //массив беззнаковых символьных переменных dt_in из 8 переменных (адреса rg и данные dt для led-драйвера)
unsigned char n; //символьная переменная (максимальное количество разрядов led-драйвера n=0,...n=7)
unsigned int count; //переменная счётчика основных циклов
unsigned char V; //переменная для передачи разложенной величины измеренного напряжения в led-драйвер
unsigned char I; //переменная для передачи разложенной величины измеренного тока в led-драйвер
unsigned int adc_value; //10-битный результат ацп-преобразования adc_code
float dt_v; //результат преобразования adc_code канала mux_4 в измеренное напряжение [V]
float Av; //Av=dt_v - входной параметр (Vin) сглаживающего фильтра в канале [V]
float Mv; //выходной параметр (Vavr_out) сглаживающего фильтра в канале [V]
float Mv1 = 0; //сброс промежуточного (Vavr) результата работы сглаживающего фильтра в канале [V]
float Ks_v = 0.025; //коэффициент сглаживания в канале [V]
float dt_i; //результат преобразования adc_code канала mux_3 в измеренный ток [I]
float Ai; //Ai=dt_i
float Mi; //окончательный результат работы сглаживающего фильтра в канале [I]
float Mi1 = 0; //сброс промежуточного результата работы сглаживающего фильтра в канале [I]
float Ks_i = 0.025; //коэффициент сглаживания в канале [I]
//--- инициализация PB1 ---
void PB1_ini(void) //функция инициализации порта PB1
{
DDRB |= (1<<PORTB1); //PB1_out (oc1a)
PORTB &= ~(1<<PORTB1); //PB1_lo
}
//--- инициализация таймера oc1a ---
void timer_ini(void) //функция таймера
{
ASSR=0x00; //сбрасываем полностью регистр assr
TCCR1A |= ((1<<COM1A1)|(1<<WGM10)); //Fast PWM oc1a, Clear OC1A on Compare Match, clkT2S/1 (no prescalling)
TCCR1B |= ((1<<WGM12)|(1<<CS10));
TCNT1H=0x00; // Timer Value = 0 сброс счётного регистра таймера oc1a
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x7F; //Output Compare Register = dec127 - заполнение шим -DC~50%
TIMSK=0x00; //сброс регистра timsk
}
//--- инициализация шины данных драйвера max7219 ---
void LED_SPI(void)
{
DDRC |= ((1<<PORTC2)|(1<<PORTC1)|(1<<PORTC0)); //PС0_out, PC1_out, PС2_out
PORTC &= ~((1<<PORTC2)|(1<<PORTC1)|(1<<PORTC0)); //PС0_lo, PC1_lo, PС2_lo
}
//--- функция побитовой отправки данных в драйвер max7219 ---
void Send_max7219(unsigned char rg, unsigned char dt)
{
unsigned char rg_copy; //копия значения переменной rg
unsigned char i; //переменная для побитной отправки данных в драйвер индикаторов
dt_in[rg] = dt; //
rg_copy = rg; //создадим копию значения переменной rg (адрес регистра led-драйвера)
DRV_CS_0; //отправим «0» на вывод CS микросхемы MAX7219, чтобы начать процесс передачи адреса и данных
asm("nop"); //пауза в 1 такт
for(i=0;i<8;i++) //цикл от 0 до 7 с шагом 1, для побитовой отправки байта адреса в микросхему MAX7219
{
if((rg & 0x80)==0x80) //пока rg * 0b1000 0000 > 0, ...
{
DRV_DT_1; //...отправим 1 на вывод Din микросхемы MAX7219
}
else //если же rg * 0b1000 0000 = 0, ...
{
DRV_DT_0; //...отправим 0 на вывод Din микросхемы MAX7219
}
//создадим тактовый импульс на выводе CLK микросхемы MAX7219
asm("nop"); //пауза в 1 такт
DRV_CLK_1; //отправим 1 на вывод Clk микросхемы MAX7219
asm("nop"); //пауза в 1 такт
DRV_CLK_0; //отправим 0 на вывод Clk микросхемы MAX7219
rg <<= 1; //сдвинем значение переменной rg на 1 бит влево
} //выйдем из цикла когда i станет равной 7, т.е. когда отправка байта адреса в микросхему MAX7219 будет окончена
for(i=0;i<8;i++) //цикл от 0 до 7 с шагом 1, для побитовой отправки байта данных в микросхему MAX7219
{
if((dt_in[rg_copy] & 0x80)==0x80) //пока rg * 0b1000 0000 > 0, ...
{
DRV_DT_1; //...отправим 1 на вывод Din микросхемы MAX7219
}
else //если же rg * 0b1000 0000 = 0, ...
{
DRV_DT_0; //отправим 0 на вывод Din микросхемы MAX7219
}
//создадим тактовый импульс на выводе CLK микросхемы MAX7219
asm("nop"); //пауза в 1 такт
DRV_CLK_1; //отправим 1 на вывод Clk микросхемы MAX7219
asm("nop"); //пауза в 1 такт
DRV_CLK_0; //отправим 0 на вывод Clk микросхемы MAX7219
dt_in[rg_copy] <<= 1; //сдвинем значение переменной DRV_MOSI на 1 бит влево
}
//выйдем из цикла когда i станет равной 7, т.е. когда отправка байта данных в микросхему MAX7219 будет окончена
DRV_CS_1; //отправим «1» на вывод CS микросхемы MAX7219, чтобы завершить процесс передачи адреса и данных
}
//--- инициализация драйвера max7219 ---
void MAX7219_ini(void)
{
Send_max7219(0x09,0xFF); //(номер регистра rg, данные dt) включаем режим BCD code B, для 0-7 разрядов
Send_max7219(0x0A,0x0A); //DC = 21/32 яркость свечения
Send_max7219(0x0B,0x07); //число используемых разрядов (0-7 разрядов)
Send_max7219(0x0C,0x01); //отключаем режим энергосбережения (Shutdown)
for(n=1;n<9;n++)
{
Send_max7219(n,0x0F); //гасим все разряды драйвера дисплея V/A до момента вывода информации
}
}
//--- функция вывода значений на display_1 (вольтметр 00.0v) ---
void ledprint_1(unsigned int number) //number - величина измеренного напряжения Mv
{
if((float)dt_v < 998) //если Mv < 99.8, то выводим на дисплей результат...
{
Digit[8]=number/100 ? number/100 : 0x0F; //сотни /гасим старший незначащий нуль
Digit[7]=number%100/10; //десятки
Digit[7]=Digit[7]|0x80; //вкл децимальную точку в разряде Digit_7
Digit[6]=number%10; //единицы
Digit[5]=0x0F; //blanking digit_5
}
else //...в противном случае, выводим на дисплей 0L (overload)
{
Digit[8]=0x0F; //blanking digit_8
Digit[7]=0x00; //<<0>>
Digit[6]=0x0D; //<<L>>
Digit[5]=0x0F; //blanking digit_5
}
for(V=6;V<9;V++) //заполняем разряды вольтметра цифрами разложенного Mv
{
dt_in[V] = Digit[V]; //
Send_max7219(V, dt_in[V]); //
}
}
//--- функция вывода значений на display_2 (амперметр 00.0а) ---
void ledprint_2(unsigned int number) //number - величина измеренного тока Mi
{
if((float)dt_i < 350) //если Mi < 35.0, то выводим на дисплей результат...
{
Digit[4]=number/100 ? number/100 : 0x0F; //сотни /гасим старший незначащий нуль
Digit[3]=number%100/10; //десятки
Digit[3]=Digit[3]|0x80; //вкл децимальную точку в разряде Digit_3
Digit[2]=number%10; //единицы
Digit[1]=0x0F; //blanking digit_1
}
else //...в противном случае, выводим на дисплей 0L (overload)
{
Digit[4]=0x0F; //blanking digit_3
Digit[3]=0x00; //<<0>>
Digit[2]=0x0D; //<<L>>
Digit[1]=0x0F; //blanking digit_1
}
for(I=2;I<5;I++) //заполняем разряды вольтметра цифрами разложенного Mi
{
dt_in[I] = Digit[I]; //
Send_max7219(I, dt_in[I]); //
}
}
//--- инициализация внутреннего ацп ---
void ADC_ini(void)
{
ADCSRA |= ((1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)); //разрешение использования АЦП, предделитель 16M/128 = 125 кГц
ADMUX &= ~((1<<REFS0)|(1<<REFS1)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0)); //внешний источник опорного напряжения Aref, сброс канала АЦП на ch_ADC=0
}
//--- функция ацп-преобразователя с переменным каналом ch_ADC ---
unsigned int ADC_Conv(unsigned char ch_ADC) //(переменная ch_ADC - канал ацп)
{
unsigned int adc_value = 0; //сброс регистра хранения результата ацп-преобразования
unsigned char set_ADMUX = ADMUX; //переменная для выбора канала АЦП
set_ADMUX &= ((1 << REFS1) | (1 << REFS0)); //оставить неизменным только Vref
set_ADMUX |= ch_ADC; //выбор канала АЦП ch_ADC
ADMUX = set_ADMUX;
_delay_us(10); //пауза 10us
ADCSRA |= (1 << ADSC); //запуск АЦП
while ((ADCSRA & (1 << ADSC))); //ожидание окончания ацп-преобразования
adc_value = ADCW; //10-битный результат ацп-преобразования (из регистров результата ADCL и ADCH)
return (unsigned int)adc_value; //выйдем из функции и вернём значение (из регистров результата ADCL и ADCH АЦП)
}
//--- функция преобразования результата оцифровки канала mux_5 в величину измеренного напряжения ---
float ADCV_Conv(void)
{
//adc_value - 10-битный результат работы ацп
float dt_v; //величина измеренного напряжения [V]
dt_v=((float)adc_value*(Vref))/Kv; //преобразование 10-битного числа типа u_int в величину измеренного напряжения (float)
return dt_v; //возвращаем величину измеренного напряжения в вольтах [V]
}
//--- функция преобразования результата оцифровки канала mux_4 в величину измеренного тока ---
float ADCI_Conv(void)
{
//adc_value - 10-битный результат работы ацп
float dt_i; //величина измеренного тока [I]
dt_i=((float)adc_value*(Vref))/Ki; //преобразование 10-битного числа типа u_short в величину измеренного тока (float)
return dt_i; //возвращаем величину измеренного тока в амперах [A]
}
//--- основная функция с бесконечным циклом ---
int main(void)
{
float dt_v=0; //очистка регистра хранения результата оцифровки канала [V]
float dt_i=0; //очистка регистра хранения результата оцифровки канала [I]
PB1_ini(); //инициализация порта PB1
timer_ini(); //инициализация инвертора +5v >> -12v
OCR1AH = 0x00; //запись в регистр сравнения...
OCR1AL = 0x7F; //...числа dec127
//SPI_ini(); //инициализация шины SPI
LED_SPI(); //инициализация шины данных LED-драйвера
MAX7219_ini(); //инициализация MAX7219
ADC_ini(); //инициализация внутреннего АЦП
//----------
while(1)
{
adc_value = ADC_Conv(5); // - считаем результат ацп-преобразования канала mux_5
dt_v = ADCV_Conv(); //преобразуем результат в величину измеренного напряжения [V]
Av=dt_v; //
Mv = Ks_v * Av + Mv1 * (1-Ks_v); //фильтр Кальмана Mn=Ks*An + Mn1*(1-Ks)
Mv1=Mv; //
_delay_us(10);
adc_value = ADC_Conv(4); // - считаем результат ацп-преобразования канала mux_4
dt_i = ADCI_Conv(); //преобразуем результат в величину измеренного тока [I]
Ai=dt_i; //
Mi = Ks_i * Ai + Mi1 * (1-Ks_i); //фильтр Кальмана Mn=Ks*An + Mn1*(1-Ks)
Mi1=Mi; //
_delay_us(10);
count++; //инкрементируем счётчик основного цикла
if(count==3000) //обновляем информацию на индикаторах в каждом 3 000 цикле
{
count=0; //сброс счётчика циклов
ledprint_1(Mv); //отправим значение в функцию вывода на индикатор вольтметра
ledprint_2(Mi); //отправим значение в функцию вывода на индикатор амперметра
}
}
}
в качестве опорного напряжения Vref = +4.1v для внутренего ацп атмеги используеца просто напряжение питания +5в это выходное напряжение чёпера +24v >>+5v на микре mcp34063 деленое синим подстроешником 3296w. палаумные и не столь отдалёные экз_п-п-перды громко пердели про "ацкую нестабильность этого гавна 34063". один прохесионал пёрнул про то, что, якобы, синии-синии подсроешники 3296 "текут"!!! текут, бл! хоть стой хоть падай. ослы ебаные понакупили совковых депломов, но как были ослами, так ими же и остались. следующий удолбаный ёб смешал с грязью достойную микру tl082. ему рэйл-ту-рэйл подавай за тыщю рупий. на меньшее он не согласен. послушал, послушал я этих прекрасных людей, сделал выводы об ихних ментальных способностях и отослал их всех на йух в печду)) всю полезную инфу дали нормальные люди, мудаков с хворумов слушать смысла совсем нетути...
Ср ноя 15, 2023 00:03:56