Расскажу про алгоритм DDS:
Создаешь таблицу одного периода синуса, чтоб укладывалось в 256 байт (чтоб не проверять переполнение указателя)
- Код: Выделить всё
;таблица синуса 1 периода в дополнительном коде
SinTab:
.db 0, 1, 2, 4, 5, 6, 7, 9
.db 10, 11, 12, 13, 15, 16, 17, 18
.db 19, 20, 21, 22, 24, 25, 26, 27
.db 28, 29, 30, 31, 32, 33, 34, 34
.db 35, 36, 37, 38, 39, 39, 40, 41
.db 42, 42, 43, 44, 44, 45, 45, 46
.db 46, 47, 47, 47, 48, 48, 49, 49
.db 49, 49, 49, 50, 50, 50, 50, 50
.db 50, 50, 50, 50, 50, 50, 49, 49
.db 49, 49, 49, 48, 48, 47, 47, 47
.db 46, 46, 45, 45, 44, 44, 43, 42
.db 42, 41, 40, 39, 39, 38, 37, 36
.db 35, 34, 34, 33, 32, 31, 30, 29
.db 28, 27, 26, 25, 24, 22, 21, 20
.db 19, 18, 17, 16, 15, 13, 12, 11
.db 10, 9, 7, 6, 5, 4, 2, 1
.db 0, 255, 254, 252, 251, 250, 249, 247
.db 246, 245, 244, 243, 241, 240, 239, 238
.db 237, 236, 235, 234, 232, 231, 230, 229
.db 228, 227, 226, 225, 224, 223, 222, 222
.db 221, 220, 219, 218, 217, 217, 216, 215
.db 214, 214, 213, 212, 212, 211, 211, 210
.db 210, 209, 209, 209, 208, 208, 207, 207
.db 207, 207, 207, 206, 206, 206, 206, 206
.db 206, 206, 206, 206, 206, 206, 207, 207
.db 207, 207, 207, 208, 208, 209, 209, 209
.db 210, 210, 211, 211, 212, 212, 213, 214
.db 214, 215, 216, 217, 217, 218, 219, 220
.db 221, 222, 222, 223, 224, 225, 226, 227
.db 228, 229, 230, 231, 232, 234, 235, 236
.db 237, 238, 239, 240, 241, 243, 244, 245
.db 246, 247, 249, 250, 251, 252, 254, 255
EndSinTab:
т.е. получили таблицу с размерностью мощности шим в один байт, каждый байт в таблице - это угол равный 360град./256. 360град - это полный период синусоиды, 256 - это размерность таблицы синуса.
Теперь определяем указатель, например: PWM_STEP_SIN, размерностью один байт, который будет бегать по нашей таблице. Начинаем его крутить с нужной частотой, обзовем PWM_DDS_FREQ (угловая скорость):
Например, каждые 2мс. прибавляем к PWM_STEP_SIN число 3 из PWM_DDS_FREQ. Если мы хотим увеличить скорость, то соотв. прибавляем большее значение. Т.к. PWM_STEP_SIN имеет такую же размерность как сама таблица, то получается автоматический переход с конца периода на начало при переполнении этого регистра. В общем, у нас крутится регистр PWM_STEP_SIN с определенной скоростью, остается считывать данные для трех синусоид сдвинутых относительно друг друга на 120 град.
Например для первой синусоиды считываем данные по адресу [PWM_STEP_SIN] и кидаем в pwm. Для 2-й синусоиды информацию берем из смещенного указателя на 120 градусов: PWM_STEP_SIN + 256*120/360. На асме так:
- Код: Выделить всё
ldi temp1,0xFF & (256*120/360) ;считать данные из таблицы для второй синусоиды (+120 градусов)
Для 3-й синусоиды соотв. сдвигаем на 240град. относительно первой: 256*240/360.Имеем 3 синусоиды сдвинутые на 120 град. Частота синусоид зависит от значения PWM_DDS_FREQ. И конечно, надо сопоставлять разрешающую способность таблицы с угловой скоростью PWM_DDS_FREQ. Чтоб PWM_DDS_FREQ не давал приращение к PWM_STEP_SIN по полпериода за раз. Иначе поимеем квадратный синус и прочие умные слова типа алиасинг

Вот щаз я особенно покассандрил
