abc писал(а):Вот Ведущий специалист - реальный монстр,
Вот здесь я с тобой абсолютно согласен...
abc писал(а):Вот Ведущий специалист - реальный монстр,
abc писал(а):Вот Ведущий специалист - реальный монстр, я его еще по опытам на ВРТП с VS1000 помню.
Мы себе давали слово
Не сходить с пути прямого,
Но так уж суждено,
И уж если откровенно - всех пугают перемены,
Но тут уж все равно.
Вот новый поворот и мотор ревет,
Что он нам несет: пропасть или взлет,
Омут или брод - и не разберешь,
Пока не повернешь.
Существуют две противоположные философии использования Силы — Светлая сторона и Тёмная сторона. Сторона выбирается в зависимости от личных морально-этических принципов. Выбор стороны — важнейший шаг в жизни любого разумного существа, умеющего направлять Силу.
Философию Светлой стороны воплощают в жизнь Джедаи.
Нет, тут дело не в танчиках вовсе. Я лично Ведущего специалиста оценил, когда он много и играючи щелкал протоколы ЖКИ-шек еще лет 8 (10?) назад.HHIMERA писал(а):О господи!!! Никогда бы не догадался, что мерилом камня выступает танчики-игруха... :)))
Специальное предложение от Atmel и Rainbow Electronics: полнофункциональный микроконтроллер на базе ядра Cortex-M0+ по цене $0.90 от 1 шт.
Основные характеристики микроконтроллера ATSAMD20G16A-AU:
64 КБ Flash-памяти и 8 КБ ОЗУ,
Тактовая частота до 48 МГц,
6 универсальных коммуникационных модулей SERCOM (конфигурируемых как UART/USART, SPI или I2C),
8 16-битных таймеров/счетчиков,
14-канальный 12-битный АЦП,
1-канальный 10-битный ЦАП,
8-канальная система событий,
Периферийный контроллер емкостных сенсоров касания, поддерживающий до 120 каналов,
Напряжение питания от 1.62 В до 3.63 В
48-выводной корпус TQFP.
Дополнительное условие специальной акции – все клиенты приобретшие микроконтроллер ATSAMD20G16A-AU, также могут приобрести оценочный комплект SAM D20 Xplain PRO и платы расширения к нему со скидкой 50%
Базовая оценочная плата SAM D20 Xplained Pro на базе микроконтроллера ATSAMD20J18, содержит встроенный отладчик цена $23
Код: Выделить всё
#include "stm32f0xx.h"
#define SegA (uint8_t)1<<0
#define SegB (uint8_t)1<<1
#define SegC (uint8_t)1<<2
#define SegD (uint8_t)1<<3
#define SegE (uint8_t)1<<4
#define SegF (uint8_t)1<<5
#define SegG (uint8_t)1<<6
#define SegH (uint8_t)1<<7
#define digit_0 (uint8_t)(SegA | SegB | SegC | SegD | SegE | SegF)
#define digit_1 (uint8_t)(SegB | SegC)
#define digit_2 (uint8_t)(SegA | SegB | SegG | SegE | SegD)
#define digit_3 (uint8_t)(SegA | SegB | SegG | SegC | SegD)
#define digit_4 (uint8_t)(SegF | SegG | SegB | SegC)
#define digit_5 (uint8_t)(SegA | SegF | SegG | SegC | SegD)
#define digit_6 (uint8_t)(SegA | SegF | SegE | SegD | SegC | SegG)
#define digit_7 (uint8_t)(SegA | SegB | SegC)
#define digit_8 (uint8_t)(SegA | SegB | SegC | SegD | SegE | SegF | SegG)
#define digit_9 (uint8_t)(SegA | SegB | SegC | SegD | SegF | SegG)
const uint8_t seg7[10] =
{
digit_0,
digit_1,
digit_2,
digit_3,
digit_4,
digit_5,
digit_6,
digit_7,
digit_8,
digit_9
};
#define SEG_GPIO_ODR GPIOB->ODR
#define SEGA GPIO_ODR_0
#define SEGB GPIO_ODR_1
#define SEGC GPIO_ODR_2
#define SEGD GPIO_ODR_3
#define SEGE GPIO_ODR_4
#define SEGF GPIO_ODR_5
#define SEGG GPIO_ODR_6
#define AN_GPIO_ODR GPIOB->ODR
#define AN1 GPIO_ODR_7
#define AN2 GPIO_ODR_8
#define AN3 GPIO_ODR_9
#define AN4 GPIO_ODR_10
#define DOT_GPIO_ODR GPIOB->ODR
#define CDOT GPIO_ODR_11
#define ADOT GPIO_ODR_12
#define DQ_1 GPIOA->MODER &= ~GPIO_MODER_MODER0_0 //Set input
#define DQ_0 GPIOA->MODER |= GPIO_MODER_MODER0_0 //Set output
#define DQ GPIOA->IDR & GPIO_IDR_0 //Input bit
#define CONVERT_TEMP (uint8_t)0x44
#define WRITE_SCRATCHPAD (uint8_t)0x4E
#define READ_SCRATCHPAD (uint8_t)0xBE
#define COPY_SCRATCHPAD (uint8_t)0x48
#define RECALL_E2 (uint8_t)0xB8
#define READ_POWER_SUPPLY (uint8_t)0xB4
#define SKIP_ROM (uint8_t)0xCC
uint8_t Presence;
int16_t Temperature;
uint8_t ds18b20[2];
__IO uint8_t SegmentIndex = 0x01;
__IO uint8_t DigitIndex = 0;
__IO uint32_t Tick = 0;
uint16_t Counter = 0;
uint8_t DigitBuffer[4];
uint16_t DotMask = 0x1800;
uint16_t DataBuffer[4*7]=
{
0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
0x017F, 0x017F, 0x017F, 0x017F, 0x017F, 0x017F, 0x017F,
0x027F, 0x027F, 0x027F, 0x027F, 0x027F, 0x027F, 0x027F,
0x047F, 0x047F, 0x047F, 0x047F, 0x047F, 0x047F, 0x047F
};
void GPIOInit(void)
{
/* GPIOB Periph clock enable */
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER |= (GPIO_MODER_MODER0_0 | GPIO_MODER_MODER1_0 |
GPIO_MODER_MODER2_0 | GPIO_MODER_MODER3_0 |
GPIO_MODER_MODER4_0 | GPIO_MODER_MODER5_0 |
GPIO_MODER_MODER6_0 | GPIO_MODER_MODER7_0 |
GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0 | GPIO_MODER_MODER10_0 |
GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0) ; /* Configure PB0-PB12 in output mode */
GPIOB->OTYPER &= ~( GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 |
GPIO_OTYPER_OT_2 | GPIO_OTYPER_OT_3 |
GPIO_OTYPER_OT_4 | GPIO_OTYPER_OT_5 |
GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7 |
GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10 |
GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_12) ; // Ensure push pull mode selected--default
GPIOB->OSPEEDR |= ( GPIO_OSPEEDER_OSPEEDR0 | GPIO_OSPEEDER_OSPEEDR1 |
GPIO_OSPEEDER_OSPEEDR2 | GPIO_OSPEEDER_OSPEEDR3 |
GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 |
GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7 |
GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10 |
GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12); //Ensure maximum speed setting (even though it is unnecessary)
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR0 | GPIO_PUPDR_PUPDR1 |
GPIO_PUPDR_PUPDR2 | GPIO_PUPDR_PUPDR3 |
GPIO_PUPDR_PUPDR4 | GPIO_PUPDR_PUPDR5 |
GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7 |
GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10 |
GPIO_PUPDR_PUPDR11 | GPIO_PUPDR_PUPDR12); //Ensure all pull up pull down resistors are disabled
DOT_GPIO_ODR ^= ADOT; // Set pin ADOT
/* GPIOA Periph clock enable */
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODER0_0; //Input
GPIOA->OTYPER |= GPIO_OTYPER_OT_0; //Open-drain
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0; //Max speed
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR0; //No pull
GPIOA->ODR &= ~GPIO_ODR_0;
}
void DMAInit(void)
{
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel5->CPAR = (uint32_t)&GPIOB->ODR; // DMA channel x peripheral address register
DMA1_Channel5->CMAR = (uint32_t)DataBuffer; // DMA channel x memory address register
DMA1_Channel5->CNDTR = 4*7; // DMA channel x number of data register
DMA1_Channel5->CCR |= DMA_CCR_MSIZE_0; // Memory size 16 bit
DMA1_Channel5->CCR |= DMA_CCR_PSIZE_0; // Peripheral size 16 bit
DMA1_Channel5->CCR |= DMA_CCR_PL_1; // Channel Priority level High
DMA1_Channel5->CCR |= DMA_CCR_MINC; // Memory increment mode
DMA1_Channel5->CCR |= DMA_CCR_CIRC; // Circular mode
DMA1_Channel5->CCR |= DMA_CCR_DIR; // Data transfer direction Memory -> Peripheral
DMA1_Channel5->CCR |= DMA_CCR_EN; // Channel enable
}
void TIM15Init(void)
{
RCC->APB2ENR |= RCC_APB2ENR_TIM15EN; // TIM15 clock enable
TIM15->PSC = 48 - 1;
TIM15->ARR = 500 - 1;
TIM15->CCR1 = 25;
TIM15->DIER |= TIM_DIER_UDE; // Upload DMA Enable
TIM15->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE; // Counter Enable
}
void Configure_RTC(void)
{
/* Enable the peripheral clock RTC */
/* (1) Enable the LSI */
/* (2) Wait while it is not ready */
/* (3) Enable PWR clock */
/* (4) Enable write in RTC domain control register */
/* (5) LSI for RTC clock */
/* (6) Disable PWR clock */
RCC->CSR |= RCC_CSR_LSION; /* (1) */
while((RCC->CSR & RCC_CSR_LSIRDY)!=RCC_CSR_LSIRDY) /* (2) */
{
/* add time out here for a robust application */
}
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* (3) */
PWR->CR |= PWR_CR_DBP; /* (4) */
RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_1; /* (5) */
RCC->APB1ENR &=~ RCC_APB1ENR_PWREN; /* (7) */
}
void Init_RTC(uint32_t Time)
{
/* RTC init mode */
/* Configure RTC */
/* (1) Write access for RTC registers */
/* (2) Enable init phase */
/* (3) Wait until it is allow to modify RTC register values */
/* (4) set prescaler, 40kHz/128 => 312 Hz, 312Hz/312 => 1Hz */
/* (5) New time in TR, 24-hour format */
/* (6) Disable init phase */
/* (7) Disable write access for RTC registers */
RTC->WPR = 0xCA; /* (1) */
RTC->WPR = 0x53; /* (1) */
RTC->ISR |= RTC_ISR_INIT; /* (2) */
while((RTC->ISR & RTC_ISR_INITF)!=RTC_ISR_INITF) /* (3) */
{
/* add time out here for a robust application */
}
RTC->PRER = 0x007F0137; /* (4) */
RTC->TR = RTC_TR_PM | Time; /* (5) */
RTC->ISR &=~ RTC_ISR_INIT; /* (6) */
RTC->WPR = 0xFE; /* (7) */
RTC->WPR = 0x64; /* (7) */
}
void Copy2Buffer()
{
uint16_t n, k = 0x00FF, c = 3;
DigitIndex = 0x01;
for (n = 0; n < 28; n++)
{
if(n==7)
{
k = 0x017F;
c = 2;
DigitIndex = 0x01;
}
if(n==14)
{
k = 0x027F;
c = 1;
DigitIndex = 0x01;
}
if(n==21)
{
k = 0x047F;
c = 0;
DigitIndex = 0x01;
}
if(DigitBuffer[c] & DigitIndex) DataBuffer[n] = ~((uint16_t)DigitIndex) & k ;
else DataBuffer[n] = k;
if(n==0) DataBuffer[n] ^= DotMask;
DigitIndex <<= 0x01;
}
}
void delay_us(uint16_t delay)
{
TIM3->PSC = 48-1; //устанавливаем предделитель
TIM3->ARR = delay; //устанавливаем значение переполнения таймера, а значит и значение при котором генерируется Событие обновления
TIM3->EGR |= TIM_EGR_UG; //Генерируем Событие обновления для записи данных в регистры PSC и ARR
TIM3->CR1 |= TIM_CR1_CEN|TIM_CR1_OPM; //Запускаем таймер записью бита CEN и устанавливаем режим Одного прохода установкой бита OPM
while ((TIM3->CR1 & TIM_CR1_CEN)!=0);
}
uint8_t OneWire_Init()
{
DQ_0; //Low LINE
delay_us(480);
DQ_1; //Hi LINE
delay_us(70);
if(!(DQ)) //Если ведомое уст-во ответило (PRESENCE PULSE) - заканчиваем этот тайм-слот (480мкс).
{
delay_us(400);
if(!(DQ)) //Если линия так и продолжает быть в низком уровне - значит это либо ошибка,
return 0; //либо на линии нет устр-в, а PRESENCE был ложным и вызван просто низким уровнем на линии.
else //В таком случае естественно возвращаем 0 (ошибка / нет устр-в на шине),
return 1; //либо 1 если все в порядке и это был "настоящий" PRESENCE PULSE.
}
else //Возвращаем 0 если отсутствовал вообще какой-либо намек на PRESENCE.
return 0;
}
void OneWire_WriteByte(uint8_t data)
{
uint8_t i;
uint8_t data_bit; //Переменная представляющая текущий бит для передачи.
for(i=0; i<8; i++) //Цикл передачи 8 бит.
{
data_bit = data; //Определяем текущий, передаваемый бит посредством сдвига и логического "И".
data_bit = (data>>i) & (uint8_t)0x01; //Для первого передаваемого бита алгоритм следующий:
//Так как при первом выполнении цикла i=0, значит все биты переменной data (она хранит передаваемый нами байт)
//сдигаются вправо на 0 позиций, т.е не сдвигаются вообще, теперь выполняем логическое "И"
//с получившимся числом, так как второй операнд равен единице, то все остальные
//7 бит переменной Data попросту обнулятся, независимо от того какими они были до
//этого. Следующий цикл (i=1) проделает эту же самую операцию со вторым битом Data и т.д.
DQ_0; //Low LINE
//Любой тайм-слот начинается ведущим уст-вом с передачи низкого уровня.
//Далее в зависимости от текущего бита для передачи, формируются временные последовательности,
//состоящие всегда из двух частей (условно):
if(data_bit == (uint8_t)0x01) //"Первая часть" тайм-слота передачи 1.
{
delay_us(1); //1мкс состояния линии "в ноль".
}
else //"Первая часть" тайм-слота для передачи 0.
{
delay_us(90); //Для передачи 0, задержим линию "в низком уровне" некоторое время.
}
DQ_1; //Возващаем линию в выс. ур.
if(data_bit == (uint8_t)0x01) //"Вторая часть" тайм-слота передачи 1, подержим линию "в единице" подольше.
{
delay_us(90);
}
else //"Вторая часть" тайм-слота передачи 0, краткий импульс вверх.
{
delay_us(1);
}
DQ_1; //По завершении передачи каждого бита линию необходимо переводить в выс. ур.
delay_us(1); //Выдерживаем минимальную задержку между тайм-слотами (1мкс.(продолжит. либого тайм-слота = 60-120мкс)).
}
}
uint8_t OneWire_ReadByte(void)
{
uint8_t i;
uint8_t Data = 0;
for(i=0; i<8; i++)
{
delay_us(1);
DQ_0; //Low LINE
//Как всегда перед передачей или приемом либого тайм-слота "опускаем линию",
delay_us(5); //давая ведомому устр-ву понять что мы готовы к приему данных.
DQ_1; //Затем возвращаем в 1 и ждем что бы устр-во успело перевести линию в низкий уровень,
delay_us(15); //либо если идет передача единицы - оставило состояние шины как есть.
if(DQ) //Если линия так и осталась при высоком уровне:
{
Data |= ((uint8_t)0x01 << i); //Проведем логическое "ИЛИ" с единицей и номером текущего бита для чтения
} //(т.е по-другому говоря установим 1). Таким образом мы получим единицы там где ведомое устр-во пере-
//давало 1 и нули во всех оставшихся случаях. Это собственно и будет то число что
//передавало ведомое устр-во.
delay_us(55); //Заканчиваем текущий тайм-слот и переходим к началу следующего...
}
return Data; //Возвращаем принятый байт.
}
void Bin2Bcd(uint16_t value) // HHIMERA(c) copypast
{
uint8_t *p = DigitBuffer;
while (value > 0)
{
*p++ = seg7[value % 10];
value /= 10;
}
}
int main(void)
{
volatile uint32_t TimeToCompute = 0;
volatile uint32_t DateToCompute = 0;
uint8_t Su = 0, LastSu = 0;
GPIOInit();
DMAInit();
TIM15Init();
Configure_RTC();
Init_RTC(0);
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // TIM3 clock enable
while (1)
{
Presence = OneWire_Init();
OneWire_WriteByte(SKIP_ROM);
OneWire_WriteByte(CONVERT_TEMP);
while(LastSu == Su)
{
TimeToCompute = RTC->TR; /* get time */
DateToCompute = RTC->DR; /* need to read date also */
Su = (uint8_t)(TimeToCompute & RTC_TR_SU);
}
LastSu = Su;
Presence = OneWire_Init();
OneWire_WriteByte(SKIP_ROM);
OneWire_WriteByte(READ_SCRATCHPAD);
ds18b20[0]=OneWire_ReadByte();
ds18b20[1]=OneWire_ReadByte();
Temperature=((((uint16_t)ds18b20[1])<<8) + ds18b20[0]) ;
Temperature*=5;
Temperature>>=3;
Bin2Bcd(Temperature);
// DigitBuffer[1] = seg7[(uint8_t)((TimeToCompute & RTC_TR_ST)>>4)];
// DigitBuffer[0] = seg7[(uint8_t)(TimeToCompute & RTC_TR_SU)];
// DigitBuffer[3] = seg7[(uint8_t)((TimeToCompute & RTC_TR_MNT)>>12)];
// DigitBuffer[2] = seg7[(uint8_t)((TimeToCompute & RTC_TR_MNU)>>8)];
// DotMask ^= 0x0800;
Copy2Buffer();
}
}

Program size (bytes): 2252
Data size (bytes): 168
BSS size (bytes): 39
Total size (bytes): 2459 (R/W Memory: 207)
Program size (bytes): 1016
Data size (bytes): 108
BSS size (bytes): 28
Total size (bytes): 1152 (R/W Memory: 136)
oleg110592 писал(а):можно решить задачу аппаратным путем с помощью USART и DMA, но подобная работа была уже проведена товарищами с другого форума - повторять не очень интересно. Да и хотелось решить задачу простым ногодрыгом (любимое занятие 8-ми битных микроконтроллеров), например это может пригодится для малоногих микроконтроллеров у которых USART возможно занят.
...................
Микросекундные задержки сделаны на таймере том же TIM3, DMA теперь управляет 15 таймер - освободил каналы 2 и 3 на будущее для USART.
там то и надо... один пин, два канала таймера и два канала ДМА...
STM32. Системный таймер SysTick.
Этот таймер не описан подробно в документации на конкретное семейство микроконтроллеров, например в том же Reference manual про него присутствует всего лишь несколько строк. Дело в том, что эти документы в основном объясняют порядок работы с периферией. А таймер SysTick расположен в ядре микроконтроллера и для всех устройств на базе ядра Cortex является стандартным. Этот таймер предназначен для формирования временных интервалов операционной системы реального времени – RTOS. Но и для других целей можно использовать периодические прерывания, формируемые этим таймером. В микроконтроллерах на ядре Cortex время перехода к обработчику прерывания строго детерминировано, что является огромным плюсом этого ядра. Таймер представляет собой 24-разрядный декрементирующий счетчик. Источником тактирования является системная тактовая частота SYSCLK, либо та же частота, но поделенная на 8 – SYSCLK/8.
Код: Выделить всё
SysTick_Config(48000); /* 1ms config */Код: Выделить всё
void SysTick_Handler(void)
{
}Уважаемый г-н Клеммер,
Около недели назад, я обнаружил невероятную информацию о LPC1114FN28 на Digikey и Mouser. Это было "LPC1114FN28 был помечен как устаревший, в настоящее время прекращено." Я подтвердил LPC1114FN28 в вашем 2014 Mid-Year снятии с производства продукции списке. (На вершине стр. 11), а также я знаю, LPC1114FN28 в списке вашего долголетия, 10-летний списке обещание. К этому списку, дата долговечность LPC1114FN28 является 2022-08-08. Здесь это архив веб-странице.
В этом году, я провел время в порт mbed SDK для некоторых из ваших продуктов. Как вы знаете, компания NXP представляет mbed как один из вашего "Сервис экосистеме". А также я знаю, 1000 + люди используют LPC1114FN28 на онлайн составителя mbed. Мы приобрели LPC1114FN28 через официального дистрибьютора компании NXP, но я никогда не получал точную информацию из этих каналов.
Так, у меня есть несколько вопросов.
- Какая информация является правильным? Будете ли вы прекратить, что в конце этого года или нет?
- Почему NXP демонстрирует противоречивую информацию? Я думал, прекращение очень важно решить для полупроводников.
Если вы прекратите, что,
- Какова ваша "обещание"? Как мы можем верить вы будете держать ваши слова с сегодняшнего дня?
- Я знаю, 1k что-то не большое количество для полупроводников, но почему вы игнорируете нас?
Надеюсь услышать ваше искреннее отношение.
С уважением,
Йошихиро Цубои
Я знаю, долговечность продукта очень важно для вас, так же, как важно NXP. И я очень ценю, что ты вновь подчеркнув важность этого микроконтроллер для проектирования деятельности более чем 1000+ клиентов с использованием mbed платформу. Мы рады сообщить вам, о своем решении немедленно восстановить часть в активную, упорядочиваемой статуса с не планируется в конце срока службы, как было сообщено на середину года список снятии продукции с производства 2014 года. Мы также будем информировать наших Дистрибьюторов этого решения, так состояние доступности на дистрибьютора сайтов должна быть обновлена, как только эта информация принимается и обрабатывается.
Здесь полная запись.oleg110592 писал(а):Технический семинар 'Перспективная продукция компании Atmel'
Если кто с форума будет, просьба сделать кратенький доклад.
oleg110592 писал(а):... Только размер немного удивил (оптимизация -OS)...
oleg110592 писал(а):Опять ядру не оставляем вообще никакой работы.