GREY писал(а):
Я как-то смущен всем этим. Там руками настроить - жопа! Может если наделать шаблонов с хорошими подсказками как то и можно руками, но всё равно сомнительно.
Хватит сопли жевать, в шоке просто.
У вас там чего, в проектах ВСЯ возможная периферия задействована, да еще в самых извратных конфигах, а скрок сдачи вчера?!
Что сложного настроить к примеру пин для дрыгоножества?
прмер - на плате 4 светодиода, хочется ими гореть/не гореть/ксорить
typedef struct
{
GPIO_TypeDef* gpio_led;
uint16_t pin_led;
uint32_t rcc_gpio_bus;
} tLedItemDef;
const tLedItemDef pcb_ledPropItems[4]=
{
// for 45.1
{ GPIOC,GPIO_Pin_9, RCC_AHBPeriph_GPIOC}, // led_green
{ GPIOC,GPIO_Pin_12, RCC_AHBPeriph_GPIOC}, // led_red
{ GPIOD,GPIO_Pin_2, RCC_AHBPeriph_GPIOD}, // led_expence
{ GPIOB,GPIO_Pin_8, RCC_AHBPeriph_GPIOB}, // led_link
};
void PCB_LedsInit(void)
{
uint8_t led_idx;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
for(led_idx = 0;led_idx<4;led_idx++)
{
RCC_AHBPeriphClockCmd(pcb_ledPropItems[led_idx].rcc_gpio_bus, ENABLE);
GPIO_InitStructure.GPIO_Pin = pcb_ledPropItems[led_idx].pin_led;
GPIO_Init(pcb_ledPropItems[led_idx].gpio_led, &GPIO_InitStructure);
}
GPIO_WriteBit(pcb_ledPropItems[0].gpio_led,pcb_ledPropItems[0].pin_led,Bit_SET);
GPIO_WriteBit(pcb_ledPropItems[1].gpio_led,pcb_ledPropItems[1].pin_led,Bit_SET);
GPIO_WriteBit(pcb_ledPropItems[2].gpio_led,pcb_ledPropItems[2].pin_led,Bit_SET);
GPIO_WriteBit(pcb_ledPropItems[3].gpio_led,pcb_ledPropItems[3].pin_led,Bit_SET);
}
void PCB_LedOn(uint8_t ledId)
{
if (ledId<4)
{
GPIO_WriteBit(pcb_ledPropItems[ledId].gpio_led,pcb_ledPropItems[ledId].pin_led,Bit_RESET);
}
}
void PCB_LedXor(uint8_t ledId)
{
if (ledId<4)
{
if ((pcb_ledPropItems[ledId].gpio_led->ODR & (pcb_ledPropItems[ledId].pin_led)) != (uint32_t)Bit_RESET)
{
pcb_ledPropItems[ledId].gpio_led->BRR = pcb_ledPropItems[ledId].pin_led;
}
else
{
pcb_ledPropItems[ledId].gpio_led->BSRR = pcb_ledPropItems[ledId].pin_led;
}
}
}
void PCB_LedOff(uint8_t ledId)
{
if (ledId<4)
{
GPIO_WriteBit(pcb_ledPropItems[ledId].gpio_led,pcb_ledPropItems[ledId].pin_led,Bit_SET);
}
}
Имеем набор функцмий с префиксом PCB_ для дрыганья ножкой и под новую плату надо только несколько строк поправить с конфигом.
Это было так офигенно сложно, да?!
Я обычно делаю свою мини библотеку низкоуровневую под конкретную плату. И в пространстве приложения уже вызывается функия типа дай сухой контактк номер 3 или включи привод.
Для уартов у меня немного сложней, приложение вообще не привязано к номеру уарта и пинам, на этапе описания платы закладываются все сериальные интерфейсы, потом оно инитится разом и даже переключение прием-передача для 485ых идет полуавтоматом.
пример для ф071
хедер
typedef void(*cpu_isrptr_t)(void);
extern uint16_t PCB_GetUartDePin(uint8_t usart_idx);
extern GPIO_TypeDef* PCB_GetUartDeGPIO(uint8_t usart_idx);
extern uint8_t PCB_GetUartIrqChannel(uint8_t usart_idx);
extern void PCB_RS485_Dir_Set(uint8_t usart_idx,uint8_t de_tx_mode);
extern USART_TypeDef* PCB_USART_Init(uint8_t usart_idx,uint32_t u_BaudRate,uint16_t u_WordLength,uint16_t u_StopBits,uint16_t u_Parity, uint8_t enable485);
// assign NVIC priority and user ISR handler to USART
extern void PCB_UsartAssignIsr(uint8_t usart_idx, uint8_t nvic_IRQChannelPreemptionPriority, uint8_t nvic_IRQChannelSubPriority, cpu_isrptr_t);
код
typedef struct
{
USART_TypeDef* usartTD;
uint32_t rcc_UsartClk;
uint32_t rcc_bus;
GPIO_TypeDef* gpio_tx;
uint16_t pin_tx;
GPIO_TypeDef* gpio_rx;
uint16_t pin_rx;
uint16_t pin_af_tx;
uint16_t pin_af_rx;
GPIO_TypeDef* gpio_de;
uint16_t pin_de;
uint32_t rcc_gpio_bus;
uint8_t nvic_IRQChannel;
uint8_t usart_AF;
} tUsartItemDef;
#define MAX_PCB_USART_ID 2
const tUsartItemDef pcb_usartPropItems[MAX_PCB_USART_ID]=
{
// for STM32F071 & XR45_1
{USART1,RCC_USART1CLK_HSI,RCC_APB2Periph_USART1, GPIOB,GPIO_Pin_6, GPIOB,GPIO_Pin_7, GPIO_PinSource6,GPIO_PinSource7, 0,0, RCC_AHBPeriph_GPIOA,USART1_IRQn,GPIO_AF_0},
{USART3,RCC_USART3CLK_HSI,RCC_APB1Periph_USART3, GPIOC,GPIO_Pin_10, GPIOC,GPIO_Pin_11, GPIO_PinSource10,GPIO_PinSource11,GPIOA,GPIO_Pin_1, RCC_AHBPeriph_GPIOA,USART3_4_IRQn,GPIO_AF_1},
};
// pointer to isr
typedef void(*cpu_isrptr_t)(void);
cpu_isrptr_t usart_irq_user_handlers[5]=
{(cpu_isrptr_t)NULL,(cpu_isrptr_t)NULL,(cpu_isrptr_t)NULL,(cpu_isrptr_t)NULL,(cpu_isrptr_t)NULL};
uint16_t PCB_GetUartDePin(uint8_t usart_idx)
{
if((usart_idx<1)||(usart_idx>MAX_PCB_USART_ID))return(0);
usart_idx--;
return(pcb_usartPropItems[usart_idx].pin_de);
}
GPIO_TypeDef* PCB_GetUartDeGPIO(uint8_t usart_idx)
{
if((usart_idx<1)||(usart_idx>MAX_PCB_USART_ID))return(NULL);
usart_idx--;
return(pcb_usartPropItems[usart_idx].gpio_de);
}
void PCB_RS485_Dir_Set(unsigned char usart_idx,uint8_t de_tx_mode)
{
if((usart_idx<1)||(usart_idx>MAX_PCB_USART_ID))return;
usart_idx--;
if (0 == pcb_usartPropItems[usart_idx].pin_de) return;
if (de_tx_mode)
{
pcb_usartPropItems[usart_idx].gpio_de->BSRR = pcb_usartPropItems[usart_idx].pin_de;
}else
{
pcb_usartPropItems[usart_idx].gpio_de->BRR = pcb_usartPropItems[usart_idx].pin_de;
}
}
uint8_t PCB_GetUartIrqChannel(uint8_t usart_idx)
{
if((usart_idx<1)||(usart_idx>MAX_PCB_USART_ID))return(0);
usart_idx--;
return(pcb_usartPropItems[usart_idx].nvic_IRQChannel);
}
USART_TypeDef* PCB_USART_Init(uint8_t usart_idx,
uint32_t u_BaudRate,
uint16_t u_WordLength,
uint16_t u_StopBits,
uint16_t u_Parity,
uint8_t enable485)
{
USART_InitTypeDef usart_InitStructure;
GPIO_InitTypeDef gpio_InitStructure;
if((usart_idx<1)||(usart_idx>MAX_PCB_USART_ID))return(NULL);
usart_idx--;
RCC_AHBPeriphClockCmd(pcb_usartPropItems[usart_idx].rcc_gpio_bus, ENABLE);
if(usart_idx == 0) // usart1 wired to a different bus
{
RCC_APB2PeriphClockCmd(pcb_usartPropItems[usart_idx].rcc_bus , ENABLE);
}else
{
RCC_APB1PeriphClockCmd(pcb_usartPropItems[usart_idx].rcc_bus , ENABLE);
}
//GPIO_DeInit(GPIOA);
RCC_USARTCLKConfig(pcb_usartPropItems[usart_idx].rcc_UsartClk);
/* Configure pins as AF pushpull */
gpio_InitStructure.GPIO_Mode = GPIO_Mode_AF;
gpio_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
gpio_InitStructure.GPIO_OType = GPIO_OType_PP;
gpio_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
gpio_InitStructure.GPIO_Pin = pcb_usartPropItems[usart_idx].pin_tx;
GPIO_Init(pcb_usartPropItems[usart_idx].gpio_tx, &gpio_InitStructure);
gpio_InitStructure.GPIO_Pin = pcb_usartPropItems[usart_idx].pin_rx;
GPIO_Init(pcb_usartPropItems[usart_idx].gpio_rx, &gpio_InitStructure);
/* Connect pin to Periph */
GPIO_PinAFConfig(pcb_usartPropItems[usart_idx].gpio_tx, pcb_usartPropItems[usart_idx].pin_af_tx, pcb_usartPropItems[usart_idx].usart_AF);
GPIO_PinAFConfig(pcb_usartPropItems[usart_idx].gpio_rx, pcb_usartPropItems[usart_idx].pin_af_rx, pcb_usartPropItems[usart_idx].usart_AF);
if((enable485)&& (0 != pcb_usartPropItems[usart_idx].pin_de))
{ // Configure 485 DE
gpio_InitStructure.GPIO_Pin = pcb_usartPropItems[usart_idx].pin_de;
gpio_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
gpio_InitStructure.GPIO_OType = GPIO_OType_PP;
gpio_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpio_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(pcb_usartPropItems[usart_idx].gpio_de, &gpio_InitStructure);
pcb_usartPropItems[usart_idx].gpio_de->BRR = pcb_usartPropItems[usart_idx].pin_de;
}
usart_InitStructure.USART_BaudRate = u_BaudRate;
usart_InitStructure.USART_WordLength = u_WordLength;
usart_InitStructure.USART_StopBits = u_StopBits;
usart_InitStructure.USART_Parity = u_Parity;
usart_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usart_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(pcb_usartPropItems[usart_idx].usartTD, &usart_InitStructure);
USART_Cmd(pcb_usartPropItems[usart_idx].usartTD, ENABLE);
//debug_usart = pcb_usartPropItems[usart_idx].usartTD;
return(pcb_usartPropItems[usart_idx].usartTD);
}
void PCB_UsartAssignIsr(uint8_t usart_idx, uint8_t nvic_IRQChannelPreemptionPriority, uint8_t nvic_IRQChannelSubPriority, cpu_isrptr_t cpu_isrptr)
{
NVIC_InitTypeDef nvic_InitStructure;
if((usart_idx<1)||(usart_idx>MAX_PCB_USART_ID))return;
usart_idx--;
usart_irq_user_handlers[usart_idx] = cpu_isrptr;
/* Enable the USARTx Interrupt */
nvic_InitStructure.NVIC_IRQChannel = pcb_usartPropItems[usart_idx].nvic_IRQChannel;
nvic_InitStructure.NVIC_IRQChannelPriority = nvic_IRQChannelPreemptionPriority;
nvic_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_InitStructure);
}
void USART1_IRQHandler(void)
{
if(usart_irq_user_handlers[0]!=NULL)
(*usart_irq_user_handlers[0])();
}
void USART3_4_IRQHandler(void)
{
if(usart_irq_user_handlers[1]!=NULL)
(*usart_irq_user_handlers[1])();
}
Когда суровый код организован таким образом, то даже портирование реальных(10-40к строк) проджектов с 8 и 16 бит под арм делается элементарно.
На самом деле особой проблемы настроить переферию нет, главное бить линейкой по пальцам за лазанье напрямую по регистрам без явной необходимости.
Работа с переферией всеравно сложней, а никакой куб в этом не поможет.
К примеру прерывание по уарту разршено для окончания переддачи и приема символа. Прерывание происходит, но оба этих флага пусты. Если забить на это болт, то это прерывание будет крутиться вечно, пока не будет устранена причина. На столе скорей всего причина никогда не возникнет, а возникнет в реальном применении, да не сразу, а когда шина будет сильно зашумлена.
И чем тут поможет куб??????